Hi. I'm in need of a validator on a transition that checks to see if the values of two select fields "Source Language" and "Target Language" are not identical. I've tried my hand at creating a script using scriptrunner that would do exactly this but it doesn't seem to be working.
Can someone with more knowledge of groovy scripting and scriptrunner for JIRA tell me where I'm going wrong and point me in the right direction?
import com.opensymphony.workflow.InvalidInputException def cfm = ComponentManager.instance.getCustomFieldManager() def src = (issue.getCustomFieldValue(cfm.getCustomFieldObject('customfield_10206')).getValue() def target = (issue.getCustomFieldValue(cfm.getCustomFieldObject('customfield_10207')).getValue() if (src.equalsIgnoreCase( target )) { invalidInputException = new InvalidInputException("Source and Target Language must not be the same.") }
Thank you kindly.
Edit: Thank you to Kostas for providing me with the answer. The completed code is as follows:
(I've edited the code to be a general solution)
import org.apache.log4j.Category; import com.atlassian.jira.ComponentManager; import com.opensymphony.workflow.InvalidInputException; import com.atlassian.jira.ComponentManager; import com.atlassian.jira.issue.CustomFieldManager; import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.issue.comments.CommentManager; import com.atlassian.jira.issue.fields.CustomField; import com.atlassian.jira.util.ImportUtils; import com.opensymphony.util.TextUtils import com.atlassian.jira.component.ComponentAccessor; CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager(); CustomField customField_1 = customFieldManager.getCustomFieldObject("customfield_id"); CustomField customField_2 = customFieldManager.getCustomFieldObject("customfield_id"); String string_1 = issue.getCustomFieldValue( customField_1 ); String string_2 = issue.getCustomFieldValue( customField_2 ); if (string_1.equals(string_2)) { throw new InvalidInputException("Validation Error") }
Community moderators have prevented the ability to post new answers.
I think something like the following will do the work for you
import org.apache.log4j.Category; import com.atlassian.jira.ComponentManager; import com.opensymphony.workflow.InvalidInputException; import com.atlassian.jira.ComponentManager; import com.atlassian.jira.issue.CustomFieldManager; import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.issue.comments.CommentManager; import com.atlassian.jira.issue.fields.CustomField; import com.atlassian.jira.util.ImportUtils; import com.opensymphony.util.TextUtils import com.atlassian.jira.component.ComponentAccessor; CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager(); CustomField customField_1 = customFieldManager.getCustomFieldObject( id ); CustomField customField_2 = customFieldManager.getCustomFieldObject( id ); if (issue.getCustomFieldValue( customField_1 ) == issue.getCustomFieldValue( customField_2 )) { invalidInputException = new InvalidInputException("Source and Target Language must not be the same.") }
Thank you for the help. Using your code and throwing the exception as Jamie suggested, I can see that the values of customField_1 and customField_2 are indeed identical. However, for whatever reason, the if statement isn't throwing the exception as it should. Is this a problem with the comparison? Is is that I'm comparing Strings and thus the regular equality operator doesn't work? I'm stumped since I see no reason otherwise as to why the validator is failing.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Try the comparison with equals statement if ((issue.getCustomFieldValue( customField_1 ).toString()).equals(issue.getCustomFieldValue( customField_2 ).toString()))
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
After further fumbling, I've managed to get it working. I'll update my question with the working code. Your code was basically right, I just had to convert the CustomField values to strings and compare those strings.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
> Is this a problem with the comparison? Is is that I'm comparing Strings and thus the regular equality operator doesn't work? I'm stumped since I see no reason otherwise as to why the validator is failing. The code as written is not comparing as strings... it will work if they are two text fields. However if they are say select fields it will compare two Option objects, even if they have the same "value" they will have different IDs. So the correct code really depends on what type of fields they are. Converting to string will work as it happens for selects and radios, because toString returns the option value.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
If Kostas answer doesn't work, try instead:
throw new InvalidInputException("Source ...")
then try to narrow down what's failing, eg removing all the logic and just throwing the invalid input ex.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
(1) Can this be used as a Condition rather than a Validator? What alterations need to be made?
(2) What is the code for the opposite condition: string_1 does NOT equal string_2? I need a condition that two fields DO match.
Thanks.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
For a condition go Script Condition -> Simple Scripted Condition.
To check two custom fields do not match:
cfValues['Name of field 1'] != cfValues['Name of field 2']
To check for equality just change the operator to ==
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
We are trying to do the same here, we are working to validate that a single select and a checkbox is not the same value, we already tried with simple validators and this script and it doesn't work, the error log is as follows:
2017-01-05 11:28:24,692 http-bio-80-exec-1185 ERROR US_EXT_Praecipio 688x119372x2 14a760t 10.0.64.47 /secure/admin/groovy/GroovyRunner.jspa [onresolve.jira.groovy.GroovyRunner] The script failed : javax.script.ScriptException: javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: issue for class: Script7 javax.script.ScriptException: javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: issue for class: Script7 at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:117) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:103) at javax.script.AbstractScriptEngine.eval(Unknown Source) at com.onresolve.jira.groovy.GroovyRunner.runFile(GroovyRunner.java:102) at com.onresolve.jira.groovy.GroovyRunner.run(GroovyRunner.java:62) at com.onresolve.jira.groovy.GroovyRunner.doExecute(GroovyRunner.java:250) <+1> (ActionSupport.java:165) at com.atlassian.jira.action.JiraActionSupport.execute(JiraActionSupport.java:82) <+7> (DefaultInterceptorChain.java:39) (NestedInterceptorChain.java:31) (ChainedInterceptor.java:16) (DefaultInterceptorChain.java:35) (GenericDispatcher.java:221) (GenericDispatcher.java:150) (JiraWebworkActionDispatcher.java:153) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) <+14> (ApplicationFilterChain.java:305) (ApplicationFilterChain.java:210) (ChainedFilterStepRunner.java:78) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (XContentTypeOptionsNoSniffFilter.java:22) (AbstractHttpFilter.java:31) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (HeaderSanitisingFilter.java:44) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) at com.atlassian.labs.botkiller.BotKillerFilter.doFilter(BotKillerFilter.java:36) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.jira.tzdetect.IncludeResourcesFilter.doFilter(IncludeResourcesFilter.java:39) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.jira.baseurl.IncludeResourcesFilter.doFilter(IncludeResourcesFilter.java:38) <+8> (AbstractHttpFilter.java:31) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) (ContextFilter.java:25) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.mywork.client.filter.ServingRequestsFilter.doFilter(ServingRequestsFilter.java:37) <+20> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AccessLogFilter.java:103) (AccessLogFilter.java:87) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (XsrfTokenAdditionRequestFilter.java:54) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (SiteMeshFilter.java:129) (SiteMeshFilter.java:77) (SitemeshPageFilter.java:124) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) at com.atlassian.labs.remoteapps.modules.permissions.ApiScopingFilter.doFilter(ApiScopingFilter.java:60) <+32> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (SecurityFilter.java:234) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (TrustedApplicationsFilter.java:98) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (BaseLoginFilter.java:169) (JiraLoginFilter.java:70) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) (OAuthFilter.java:55) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (ProfilingFilter.java:99) (JIRAProfilingFilter.java:19) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AbstractJohnsonFilter.java:71) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176) at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145) at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92) <+9> (UrlRewriteFilter.java:394) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (GzipFilter.java:74) (GzipFilter.java:51) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (IteratingFilterChain.java:46) (DelegatingPluginFilter.java:66) at com.atlassian.labs.remoteapps.modules.oauth.OAuth2LOFilter.doFilter(OAuth2LOFilter.java:70) <+3> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) at com.atlassian.labs.remoteapps.util.http.bigpipe.RequestIdSettingFilter.doFilter(RequestIdSettingFilter.java:22) <+43> (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (DelegatingPluginFilter.java:66) (JWDSendRedirectFilter.java:25) (DelegatingPluginFilter.java:74) (IteratingFilterChain.java:42) (ServletFilterModuleContainerFilter.java:77) (ServletFilterModuleContainerFilter.java:63) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (ChainedFilterStepRunner.java:78) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AbstractCachingFilter.java:33) (AbstractHttpFilter.java:31) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (AbstractEncodingFilter.java:41) (AbstractHttpFilter.java:31) (PathMatchingEncodingFilter.java:49) (AbstractHttpFilter.java:31) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (JiraStartupChecklistFilter.java:74) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (MultiTenantServletFilter.java:91) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (ChainedFilterStepRunner.java:78) (ApplicationFilterChain.java:243) (ApplicationFilterChain.java:210) (StandardWrapperValve.java:225) (StandardContextValve.java:123) (AuthenticatorBase.java:472) (StandardHostValve.java:168) (ErrorReportValve.java:98) (StandardEngineValve.java:118) (AccessLogValve.java:927) (CoyoteAdapter.java:407) (AbstractHttp11Processor.java:1001) (AbstractProtocol.java:585) (JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: issue for class: Script7 at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:318) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:111) ... 163 more Caused by: groovy.lang.MissingPropertyException: No such property: issue for class: Script7 at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:231) at Script7.run(Script7.groovy:19) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:315) ... 164 more 2017-01-05 11:29:16,381 http-bio-80-exec-1210 ERROR US_EXT_Praecipio 689x119650x4 14a760t 10.0.64.47 /secure/QuickCreateIssue.jspa [groovy.canned.utils.ConditionUtils] javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method contains() on null object 2017-01-05 11:34:42,548 http-bio-80-exec-1213 ERROR US_EXT_Praecipio 694x121378x1 14a760t 10.0.64.47 /secure/QuickCreateIssue.jspa [groovy.canned.utils.ConditionUtils] javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method contains() on null object 2017-01-05 11:40:03,105 http-bio-80-exec-1222 INFO KC6P 700x123208x1 11y5iwy 10.0.85.77 /secure/WorkflowUIDispatcher.jspa [jira.web.action.XsrfErrorAction] The security token is missing for 'KC6P'. User-Agent : 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)' 2017-01-05 11:42:41,985 http-bio-80-exec-1267 ERROR US_EXT_Praecipio 702x123690x1 14a760t 10.0.64.47 /secure/QuickCreateIssue.jspa [groovy.canned.utils.ConditionUtils] javax.script.ScriptException: java.lang.NullPointerException: Cannot invoke method contains() on null object
Please keep in mind this is an old environment, script runner is version 2, so I wonder if that's the case.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
can you post your script, all versions, and a screenshot of the config pls.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here's the script called fieldcomparison.groovy
import org.apache.log4j.Category; import com.atlassian.jira.ComponentManager; import com.opensymphony.workflow.InvalidInputException; import com.atlassian.jira.ComponentManager; import com.atlassian.jira.issue.CustomFieldManager; import com.atlassian.jira.issue.Issue; import com.atlassian.jira.issue.MutableIssue; import com.atlassian.jira.issue.comments.CommentManager; import com.atlassian.jira.issue.fields.CustomField; import com.atlassian.jira.util.ImportUtils; import com.opensymphony.util.TextUtils import com.atlassian.jira.component.ComponentAccessor; CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager(); CustomField customField_1 = customFieldManager.getCustomFieldObject("customfield_10555"); CustomField customField_2 = customFieldManager.getCustomFieldObject("customfield_10550"); String string_1 = issue.getCustomFieldValue( customField_1 ); String string_2 = issue.getCustomFieldValue( customField_2 ); if (string_1.equals(string_2)) { throw new InvalidInputException("Validation Error") }
JIRA version is 5.2, script runner is 2.1.2, and I don't know which configuration do you need, we are setting the script as a validator script under the open step of a workflow, we are just adding the path to the script, this means the issue doesn't exist still when running the script, we want this to validate before the issue gets created.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Community moderators have prevented the ability to post new answers.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.