Hi Everyone,
I've created a groovy scripted field whose script sums the amount of estimated of hour in the sub-tasks of a story:
import com.atlassian.jira.ComponentManager import com.atlassian.jira.issue.Issue def componentManager = ComponentManager.getInstance() def ssa = componentManager.getSubTaskManager().getSubTaskObjects(issue)//.toArray() def int size = ssa.size() if (size > 0){ def double sum = 0 for (int i = 0; i < size; i++){ sum = sum + ssa[i].getEstimate() } def double res = sum / 3600 return res } else { return null }
It works fine and nothing appreas in the logs but as soon as I start a reindexing of the server, this error message is tracked in the logs:
/secure/admin/jira/IndexReIndex.jspa [onresolve.jira.groovy.GroovyCustomField] javax.script.ScriptException: java.lang.NullPointerException javax.script.ScriptException: javax.script.ScriptException: java.lang.NullPointerException at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:117) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233) at javax.script.ScriptEngine$eval.call(Unknown Source) at com.onresolve.jira.groovy.GroovyCustomField.getValueFromIssue(GroovyCustomField.groovy:160) at com.atlassian.jira.issue.fields.CustomFieldImpl.getValue(CustomFieldImpl.java:395) at com.atlassian.jira.issue.index.indexers.impl.NumberCustomFieldIndexer.addDocumentFields(NumberCustomFieldIndexer.java:41) at com.atlassian.jira.issue.index.indexers.impl.NumberCustomFieldIndexer.addDocumentFieldsNotSearchable(NumberCustomFieldIndexer.java:36) at com.atlassian.jira.issue.index.indexers.impl.AbstractCustomFieldIndexer.addIndex(AbstractCustomFieldIndexer.java:50) at com.atlassian.jira.issue.index.IssueDocument.getDocument(IssueDocument.java:41) at com.atlassian.jira.issue.index.DefaultIssueDocumentFactory.get(DefaultIssueDocumentFactory.java:15) at com.atlassian.jira.issue.index.DefaultIssueDocumentFactory.get(DefaultIssueDocumentFactory.java:11) at com.atlassian.jira.issue.index.DefaultIssueIndexer$IssueLockDocumentCreationStrategy$2.get(DefaultIssueIndexer.java:598) at com.atlassian.jira.issue.index.DefaultIssueIndexer$IssueLockDocumentCreationStrategy$2.get(DefaultIssueIndexer.java:593) at com.atlassian.util.concurrent.ManagedLocks$ManagedLockImpl.withLock(ManagedLocks.java:303) at com.atlassian.jira.issue.index.DefaultIssueIndexer$IssueLockDocumentCreationStrategy.get(DefaultIssueIndexer.java:592) at com.atlassian.jira.issue.index.DefaultIssueIndexer$2.perform(DefaultIssueIndexer.java:158) at com.atlassian.jira.issue.index.DefaultIssueIndexer$4$1.get(DefaultIssueIndexer.java:284) at com.atlassian.jira.issue.index.DefaultIssueIndexer$4$1.get(DefaultIssueIndexer.java:280) at com.atlassian.jira.index.SimpleIndexingStrategy.get(SimpleIndexingStrategy.java:9) at com.atlassian.jira.index.SimpleIndexingStrategy.get(SimpleIndexingStrategy.java:5) at com.atlassian.jira.issue.index.DefaultIssueIndexer$4.consume(DefaultIssueIndexer.java:279) at com.atlassian.jira.issue.index.DefaultIssueIndexer$4.consume(DefaultIssueIndexer.java:272) at com.atlassian.jira.issue.util.DatabaseIssuesIterable.foreach(DatabaseIssuesIterable.java:66) at com.atlassian.jira.issue.index.DefaultIssueIndexer.perform(DefaultIssueIndexer.java:271) at com.atlassian.jira.issue.index.DefaultIssueIndexer.reindexIssues(DefaultIssueIndexer.java:153) at com.atlassian.jira.issue.index.DefaultIndexManager.doBackgroundReindex(DefaultIndexManager.java:801) at com.atlassian.jira.issue.index.DefaultIndexManager.reIndexAll(DefaultIndexManager.java:320) at com.atlassian.jira.issue.index.DefaultIndexManager.reIndexAllIssuesInBackground(DefaultIndexManager.java:367) <+3> (NativeMethodAccessorImpl.java:57) (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.atlassian.util.profiling.object.ObjectProfiler.profiledInvoke(ObjectProfiler.java:83) at com.atlassian.jira.config.component.SwitchingInvocationHandler.invoke(SwitchingInvocationHandler.java:28) at com.sun.proxy.$Proxy124.reIndexAllIssuesInBackground(Unknown Source) at com.atlassian.jira.util.index.CompositeIndexLifecycleManager.reIndexAllIssuesInBackground(CompositeIndexLifecycleManager.java:83) at com.atlassian.jira.web.action.admin.index.ReIndexBackgroundIndexerCommand.doReindex(ReIndexBackgroundIndexerCommand.java:27) at com.atlassian.jira.web.action.admin.index.AbstractAsyncIndexerCommand.call(AbstractAsyncIndexerCommand.java:54) at com.atlassian.jira.web.action.admin.index.ReIndexBackgroundIndexerCommand.call(ReIndexBackgroundIndexerCommand.java:15) at com.atlassian.jira.web.action.admin.index.AbstractAsyncIndexerCommand.call(AbstractAsyncIndexerCommand.java:23) at com.atlassian.jira.task.TaskManagerImpl$TaskCallableDecorator.call(TaskManagerImpl.java:365) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at com.atlassian.jira.task.ForkedThreadExecutor$ForkedRunnableDecorator.run(ForkedThreadExecutor.java:249) at java.lang.Thread.run(Thread.java:744) Caused by: javax.script.ScriptException: java.lang.NullPointerException at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:318) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:111) ... 45 more Caused by: java.lang.NullPointerException at org.codehaus.groovy.runtime.dgmimpl.NumberNumberPlus$DoubleLong.call(NumberNumberPlus.java:153) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:315) ... 46 more
I must add that the reindexing process reaches its end though.
Could anyone help by suggesting any element I should add to the script to make it safer?
Many thanks,
Emmanuel
Community moderators have prevented the ability to post new answers.
In scripted fields you should assume that every field value could be null. You should check every possible null value.
sum = sum + ssa[i].getEstimate()?:0
could fix the error.
Maybe
def
int
size
= ssa?.
size
()?:0
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for your reply, I made the change but I'm still facing this issue
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Could you try this?
import com.atlassian.jira.component.ComponentAccessor def sum = 0 ComponentAccessor.getSubTaskManager().getSubTaskObjects(issue)?.each{ subtask -> sum += (subtask?.getEstimate())?:0 } return (sum/3600) as Double
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Definitely nicer than my prehistoric version... and removing every error from the logs.
I've just added if (sum !=0) {return (sum/3600) as Double} else return null to ensure this field won't show up on issues with no sub-tasks.
Thanks a lot!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am facing similar issues for long time now.
I decided to add try/catch on every scripted field.
I know it's not "best practice" but it may help to clear the logs when the exceptions are hard to find.
In case of exception I return "error" for text fields so I wont loss trace, or null in others field types.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
try/catch will get you indexing again, but if there are exceptions you should look at them, rather than letting them fill your logs!
As Henning said, think about every eventuality. However I wouldn't go so far as checking whether issue.subTasks() is null etc... it should not be, according to the API.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
try/catch will eliminate the exceptions from your logs, since its been "handeled" - and therefor not raised to caller of the script.
Still - ignoring it is not good practice!
But when you have lots of issues and complicated script fields - it could be handy.
For example - if you have problems in you production environment - you can use try/catch to eliminate the problem from the logs, while debuging the problem in a dev env.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.