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

Next challenges

Recent achievements

  • Global
  • Personal

Recognition

  • Give kudos
  • Received
  • Given

Leaderboard

  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Make Other Custom Fields Required Based On Checkbox Selected Options Edited

Dear community,

I'm starting with Groovy, and I have a request from our business to make some fields required based on select options of a checkbox custom field.

I'm using ScriptRunner's behaviours feature to do it, but I'm struggling with some exceptions.

Here's my code:

// options/ Agile Team Capacity Impact is a checkbox custom field whith 4 available options
//Agile/Project Team Expansion - Start Date
//Existing Agile / Project Team - Scrum Master and Security Champion Required
//if New Agile /Project Team Staffing - Start Date
//if Non-SI IT Impact: Only 3rd Party/Other Siemens Unit is selected - Nothing to do
import com.onresolve.jira.groovy.user.FieldBehaviours
import org.apache.log4j.Logger
import org.apache.log4j.Level
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

// Get the logger and set the log level
def log = Logger.getLogger(getClass())
log.setLevel(Level.DEBUG)

// The name of the field to populate base on the value selected in the checkbox field associated with the script
final firstOptionFieldName = 'Start Date'
final secondOptionFieldName = 'Scrum Master'
final thirdOptionFieldName = 'Security Champion'

// Get the fields
def firstOptionField = getFieldByName(firstOptionFieldName)
def secondOptionField = getFieldByName(secondOptionFieldName)
def thirdOptionField = getFieldByName(thirdOptionFieldName)
def checkBoxField = getFieldById("Agile Team Capacity Impact")
def checkBoxFieldValue = checkBoxField.value

// Collect the selected checkbox values
log.debug("The checkbox field value: '${checkBoxFieldValue}' of type '${checkBoxFieldValue.class.simpleName}'")
def chosenValuesList = []
if (checkBoxFieldValue in String) {
chosenValuesList.add(checkBoxFieldValue)
} else if (checkBoxFieldValue in ArrayList) {
chosenValuesList.addAll(checkBoxFieldValue)
}

// If the user has selected "Agile/Project Team Expansion" force to populate the 'Start Date' field:
if (("Agile/Project Team Expansion" in chosenValuesList) && chosenValuesList.size() == 1) {
checkBoxField.clearError()
firstOptionField.setRequired(true)
log.error "Agile/Project Team Expansion is selected, force to populate the Start Date"


// If the user has selected "Agile/Project Team Expansion" and another value, show an error:
} else if (("Existing Agile / Project Team" in chosenValuesList) && chosenValuesList.size() > 1) {
checkBoxField.setError('If Existing Agile / Project Team is selected Scrum Master and Security Champion are required')
secondOptionField.setRequired(true)
thirdOptionField.setRequired(true)
log.error "MESSAGE:If Existing Agile / Project Team is selected Scrum Master and Security Champion are required"

} else if (("New Agile /Project Team" in chosenValuesList) && chosenValuesList.size() > 1) {
checkBoxField.setError('If New Agile /Project Team is selected "Start Date" is required"')
firstOptionField.setRequired(true)
log.error "MESSAGE:If New Agile /Project Team is selected Start Date is required"

// If the user didn't select any value, or has selected some values, but NOT the "None" value, force to populate the other field:
} else {
checkBoxField.clearError()
firstOptionField.setRequired(false)
secondOptionField.setRequired(false)
thirdOptionField.setRequired(false)
log.error "MESSAGE:First Field attempt"
}
/ options/ Agile Team Capacity Impact is a checkbox custom field whith 4








I would appreciate it if you could help me to troubleshoot the errors below:

2020-11-19 12:33:45,585+0100 http-nio-8080-exec-17 INFO MyUser 753x23698x1 18lz4dl 165.225.92.214,10.130.95.73 /secure/QuickEditIssue.jspa [c.a.j.p.webhooks.matcher.JqlEventMatcher_SLOW] JQL query '{project = "TEST"} AND {key in ("SIITLPM-51")}' produced lucene query and took '251' ms to run.
2020-11-19 12:33:45,903+0100 http-nio-8080-exec-23 WARN MyUser 753x23699x1 18lz4dl 165.225.92.214,10.130.95.73 /secure/AjaxIssueAction!default.jspa [c.a.j.p.webfragment.conditions.EntityPropertyEqualToCondition] Deprecation Warning: EntityPropertyEqualToCondition was not equivalent by JSON comparison but was by String comparison. Please ensure that the entity property values and the condition 'value' are of the same json type. Type coercion has made the actual value: '"false"' be equivalent to the expected value'false'. Please update the expected 'value' in the entity property conditionto match the actual value. This web fragment has the location: NO_LOCATION_AVAILABLE
2020-11-19 12:33:45,981+0100 http-nio-8080-exec-23 WARN MyUser 753x23699x1 18lz4dl 165.225.92.214,10.130.95.73 /secure/AjaxIssueAction!default.jspa [c.a.j.p.webfragment.conditions.EntityPropertyEqualToCondition] Deprecation Warning: EntityPropertyEqualToCondition was not equivalent by JSON comparison but was by String comparison. Please ensure that the entity property values and the condition 'value' are of the same json type. Type coercion has made the actual value: '"false"' be equivalent to the expected value'false'. Please update the expected 'value' in the entity property conditionto match the actual value. This web fragment has the location: NO_LOCATION_AVAILABLE
2020-11-19 12:33:46,432+0100 http-nio-8080-exec-36 ERROR MyUser 753x23704x2 18lz4dl 165.225.92.214,10.130.95.73 /rest/scriptrunner/behaviours/latest/validators.json [c.o.jira.behaviours.BehaviourManagerImpl] *************************************************************************************
2020-11-19 12:33:46,434+0100 http-nio-8080-exec-36 ERROR MyUser 753x23704x2 18lz4dl 165.225.92.214,10.130.95.73 /rest/scriptrunner/behaviours/latest/validators.json [c.o.jira.behaviours.BehaviourManagerImpl] Script function failed on issue: issue: SIITLPM-51, user: MyUser, fieldId: __init__, file: <inline script>
java.lang.NullPointerException: Cannot get property 'class' on null object
at 673a3bfc595c4843a816e61033b81779.run(673a3bfc595c4843a816e61033b81779.groovy:25)
at com.onresolve.jira.behaviours.BehaviourManagerImpl$_runValidator_closure2.doCall(BehaviourManagerImpl.groovy:194)
at com.onresolve.jira.behaviours.BehaviourManagerImpl.runValidator(BehaviourManagerImpl.groovy:141)
at com.onresolve.jira.behaviours.restservice.BehavioursEndpoint.getBehavioursAndRunInitialiser(BehavioursEndpoint.groovy:207)
at com.onresolve.jira.behaviours.restservice.BehavioursEndpoint$_getValidatorsFromIssueId_closure1.doCall(BehavioursEndpoint.groovy:85)
at com.onresolve.jira.behaviours.restservice.BehavioursEndpoint$_getValidatorsFromIssueId_closure1.doCall(BehavioursEndpoint.groovy)
at com.sun.proxy.$Proxy4749.get(Unknown Source)
at com.onresolve.jira.behaviours.restservice.BehavioursEndpoint.withServletThreadLocal(BehavioursEndpoint.groovy:222)
at com.onresolve.jira.behaviours.restservice.BehavioursEndpoint.getValidatorsFromIssueId(BehavioursEndpoint.groovy:77)
... 19 filtered
at com.atlassian.plugins.rest.module.RestDelegatingServletFilter$JerseyOsgiServletContainer.doFilter(RestDelegatingServletFilter.java:160)
... 1 filtered
at com.atlassian.plugins.rest.module.RestDelegatingServletFilter.doFilter(RestDelegatingServletFilter.java:70)
... 32 filtered
at com.atlassian.servicedesk.internal.web.ExternalCustomerLockoutFilter.doFilter(ExternalCustomerLockoutFilter.java:55)
... 8 filtered
at com.atlassian.jira.plugin.mobile.web.filter.MobileAppRequestFilter.doFilter(MobileAppRequestFilter.java:37)
... 4 filtered
at com.atlassian.jira.plugin.mobile.login.MobileLoginSuccessFilter.doFilter(MobileLoginSuccessFilter.java:54)
... 3 filtered
at com.atlassian.diagnostics.internal.platform.monitor.http.HttpRequestMonitoringFilter.doFilter(HttpRequestMonitoringFilter.java:55)
... 8 filtered
at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21)
... 46 filtered
at com.resolution.atlasplugins.samlsso.servlet.RedirectToSsoFilter.doFilter(RedirectToSsoFilter.java:60)
... 14 filtered
at com.atlassian.jira.security.JiraSecurityFilter.lambda$doFilter$0(JiraSecurityFilter.java:66)
... 1 filtered
at com.atlassian.jira.security.JiraSecurityFilter.doFilter(JiraSecurityFilter.java:64)
... 16 filtered
at com.atlassian.plugins.rest.module.servlet.RestSeraphFilter.doFilter(RestSeraphFilter.java:38)
... 19 filtered
at com.atlassian.jira.servermetrics.CorrelationIdPopulatorFilter.doFilter(CorrelationIdPopulatorFilter.java:30)
... 5 filtered
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.lambda$invokeFilterChain$0(CustomerContextSettingFilter.java:216)
at com.atlassian.servicedesk.internal.api.util.context.ReentrantThreadLocalBasedCodeContext.rteInvoke(ReentrantThreadLocalBasedCodeContext.java:136)
at com.atlassian.servicedesk.internal.api.util.context.ReentrantThreadLocalBasedCodeContext.runOutOfContext(ReentrantThreadLocalBasedCodeContext.java:89)
at com.atlassian.servicedesk.internal.utils.context.CustomerContextServiceImpl.runOutOfCustomerContext(CustomerContextServiceImpl.java:47)
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.outOfCustomerContext(CustomerContextSettingFilter.java:207)
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.doFilterImpl(CustomerContextSettingFilter.java:135)
at com.atlassian.servicedesk.internal.web.CustomerContextSettingFilter.doFilter(CustomerContextSettingFilter.java:124)
... 9 filtered
at com.atlassian.jwt.internal.servlet.JwtAuthFilter.doFilter(JwtAuthFilter.java:37)
... 3 filtered
at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21)
... 4 filtered
at com.atlassian.web.servlet.plugin.LocationCleanerFilter.doFilter(LocationCleanerFilter.java:36)
... 26 filtered
at com.atlassian.jira.servermetrics.MetricsCollectorFilter.doFilter(MetricsCollectorFilter.java:25)
... 25 filtered
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)




Behaviours.pngCustomFields.png

Best Regards
Luis

2 answers

2 accepted

0 votes
Answer accepted
Guilhem Dupuy Community Leader Nov 19, 2020

Hi Luis,

Have you tried the Dynamic Forms option of the Extension for Jira Service Management Add-On ? I've implemented such a solution in an instance, it works perfectly and it's really easy to configure and maintain.

You'll find it here .

Let me know if it helped,

Guilhem

Hi @Guilhem Dupuy ,

Thanks for your tip. Unfortunately, we don't have this app. 
We have ScriptRunner, and JWME. Do you think that it would be possible by using them?

Best Regards
Luis

Guilhem Dupuy Community Leader Jan 13, 2021

I know that this is probably doable using ScriptRunner but I am not a ScriptRunner expert, I don't know how, sorry :/

0 votes
Answer accepted
import com.onresolve.jira.groovy.user.FieldBehaviours
import org.apache.log4j.Logger
import org.apache.log4j.Level
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

// Get the logger and set the log level
def log = Logger.getLogger(getClass())// Get the logger and set the log level
//def log = Logger.getLogger(getClass())
log.setLevel(Level.DEBUG)

// The name of the field to populate base on the value selected in the checkbox field associated with the script
final staffingDateFieldName = 'Start Date'
final scrumMasterFieldName = 'Scrum Master'
final securityChampionFieldName = 'Security Champion'

// Get the fields
def staffingDateField = getFieldById("customfield_11700")
def scrumMasterField = getFieldById("customfield_13002")
def securityChampionField = getFieldById("customfield_13006")
def checkBoxField = getFieldById("customfield_12610")
def checkBoxFieldValue = checkBoxField.value
def checkBoxFieldName = checkBoxField.label
def value = checkBoxField.getValue()

// Collect the selected checkbox values
//log.debug("The checkbox field value: '${checkBoxFieldValue}' of type '${checkBoxFieldValue.class.simpleName}'")
def chosenValue = checkBoxFieldValue

// Clear any "cache" data from the issue
checkBoxField.clearError()
staffingDateField.setRequired(false)
scrumMasterField.setRequired(false)
securityChampionField.setRequired(false)

//if (checkBoxFieldValue) {
// log.debug("The checkbox field value: '${checkBoxFieldValue}' of type '${checkBoxFieldValue.class.simpleName}'")
//} else {
// log.debug("No value from checkbox :${checkBoxField} is selected")
// log.debug("No value from checkbox :${staffingDateField} is selected")
//}

switch(chosenValue) {
case "Agile Team Expansion":
checkBoxField.clearError()
// if(staffingDateField.value==""){
// checkBoxField.setError('"Existing Agile / Project Team" is selected "Scrum Master " and " Security Champion " are required')
// }
checkBoxField.setError('"Agile/Project Team Expansion" is selected, " Start Date " is required')
staffingDateField.setRequired(true)
scrumMasterField.setRequired(false)
securityChampionField.setRequired(false)
checkBoxField.clearError()
if (value.getClass().getName().toString() != "java.lang.String") {
def values = value as ArrayList
if(values.size() > 1){
checkBoxField.setError("Only one value is allowed for this field: " + values.size() + " currently selected")
}
} else {
checkBoxField.clearError()
}

break
case "Existing Team":
checkBoxField.clearError()
// if(scrumMasterField.value=="" && securityChampionField.value==""){
// checkBoxField.setError('"Existing Agile / Project Team" is selected " Scrum Master " and " Security Champion " are required')
// }
staffingDateField.setRequired(false)
scrumMasterField.setRequired(true)
securityChampionField.setRequired(true)
checkBoxField.clearError()
if (value.getClass().getName().toString() != "java.lang.String") {
def values = value as ArrayList
if(values.size() > 1){
checkBoxField.setError(" Only one value is allowed for this field: " + values.size() + " currently selected")
}
} else {
checkBoxField.clearError()
}
break
case "New Agile Team":
checkBoxField.clearError()
// if(staffingDateField.value==""){
// checkBoxField.setError('"New Agile /Project Team Staffing" selected, " Start Date " is required')
// }
staffingDateField.setRequired(true)
scrumMasterField.setRequired(false)
securityChampionField.setRequired(false)
checkBoxField.clearError()
break
default:
checkBoxField.clearError()
staffingDateField.setRequired(false)
scrumMasterField.setRequired(false)
securityChampionField.setRequired(false)
checkBoxField.clearError()
if (value.getClass().getName().toString() != "java.lang.String") {
def values = value as ArrayList
if(values.size() > 1){
checkBoxField.setError("Only one value is allowed for this field: " + values.size() + " currently selected")
}
} else {
checkBoxField.clearError()
}
}

 This code matched all of my requirements. 

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
TAGS
Community showcase
Published in Jira

Announcing the waitlist for Jira Work Management

Hey there Cloud Community members! We’re excited to give you the first glimpse of the new home for business teams on Jira — Jira Work Management. Jira Work Management is the next generation of J...

640 views 10 16
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you