Answer by Francis Martens (Exalate) on 23 September 2020
> Based on the destination bugs, source bug1 should change the status.
What are the business rules
Comments:
Venkatesh Pokala commented on 23 September 2020
1. Here I have one source project and 3 destinations projects.
2. I created the 3 different connections with status mapping ( SOURCE_to_DESTProject1, SOURCE_to_DESTProject2 and SOURCE_to_DESTProject3).
3. From Source BUG1 - Exalated by using connection SOURCE_to_DESTProject1
4. From the same Source BUG1- Exalated by using connection SOURCE_to_DESTProject2
5. From the same Source BUG1- Exalated by using connection SOURCE_to_DESTProject3
6. So, now one Source BUG1 cloned to 3 Bugs to 3 different projects.
7. My CASE If all 3 BUGS moved to āIN PROGRESSā then SOURCE BUG1 SHOULD MOVE TO āIN PROGRESSā
Hope this will clear everything.
Thanks,
Venkatesh.
Francis Martens (Exalate) commented on 23 September 2020
What you can do is to track the remote status in 3 custom fields on the source bug
When all 3 turn to āIn progressā, you can transition the local also.
Ie
On connection 1 - add in your incoming sync
issue.customFields."Remote Status Connection 1".value = replica.status.name
On connection 2 - add in your incoming sync
issue.customFields."Remote Status Connection 2".value = replica.status.name
On connection 3 - add in your incoming sync
issue.customFields."Remote Status Connection 3".value = replica.status.name
And then in each connection add something like
if (replica.status.name == "In Progress" && issue.customFields."Remote Status Connection 2".value == "In Progress" && issue.customFields."Remote Status Connection 3".value == "In Progress") { issue.status = "In Progress
}
Francis Martens (Exalate) commented on 25 September 2020
Hi Venkatesh Pokala
I see you raised the same question on the Atlassian community site, which is totally fine
https://community.atlassian.com/t5/Jira-discussions/One-bug-should-clone-to-many-other-projects-locally/m-p/1490575
Iām just wondering if my suggestion here is not sufficient for you to continue with your implementation.
Venkatesh Pokala commented on 25 September 2020
Hi Francis Martens (Exalate),
I tried your suggested way, but not working as expected. See the below logs and other script details. I really need your quick help to proceed further.
Impact: ISSUELocal entity: F6755-5Remote entity: LAX20-225Connection: F6755_to_LAX20Error type: Incoming sync: update sync errorError Creation Time: 2020-08-05 23:23:37.384Error Detail Message: Script error for issue F6755-5. Details: Cannot get property 'Remote Status RAX20' on null object.
Error line: Script109.groovy:39 Error Stack Trace: com.exalate.api.exception.script.ChangeProcessorException: Script error for issue F6755-5. Details: Cannot get property 'Remote Status RAX20' on null object.
Error line: Script109.groovy:39
at com.exalate.error.services.ScriptExceptionCategoryService$.wrapAsChangeProcessorException(ScriptExceptionCategoryService.scala:58)
at com.exalate.processor.jira.JiraChangeIssueProcessor.changeIssue(JiraChangeIssueProcessor.java:163)
at com.exalate.replication.request.UpdateIssueSyncRequestState.transition(UpdateIssueSyncRequestState.java:115)
at com.exalate.replication.request.UpdateIssueSyncRequestState.transition(UpdateIssueSyncRequestState.java:33)
at com.exalate.replication.in.RequestProcessorService.processSyncRequest(RequestProcessorService.java:324)
at com.exalate.replication.in.RequestProcessorService.processSyncRequestsForIssue(RequestProcessorService.java:194)
at com.exalate.replication.in.RequestProcessorService.processSyncRequests(RequestProcessorService.java:131)
at com.exalate.replication.in.RequestWorker$1.run(RequestWorker.java:88)
at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService$1.run(ClusteredSensitiveExecutorService.java:32)
at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService$1.run(ClusteredSensitiveExecutorService.java:28)
at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.executeHandlingLocks(ClusteredSensitiveExecutorService.java:48)
at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.executeHandlingLocks(ClusteredSensitiveExecutorService.java:28)
at com.exalate.replication.in.RequestWorker.run(RequestWorker.java:78)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.exalate.api.exception.script.ScriptException: Cannot get property 'Remote Status RAX20' on null object.
Error line: Script109.groovy:39
at com.exalate.error.services.ScriptExceptionCategoryService.categorizeProcessorAndIssueTrackerExceptionsIntoScriptExceptions(ScriptExceptionCategoryService.scala:36)
at com.exalate.processor.ExalateProcessor.executeProcessor(ExalateProcessor.java:48)
at com.exalate.processor.jira.JiraChangeIssueProcessor.executeChangeProcessor(JiraChangeIssueProcessor.java:236)
at com.exalate.processor.jira.JiraChangeIssueProcessor.changeIssue(JiraChangeIssueProcessor.java:139)
... 18 more
Caused by: javax.script.ScriptException: javax.script.ScriptException: java.lang.NullPointerException: Cannot get property 'Remote Status RAX20' on null object
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:151)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at com.exalate.processor.ExalateProcessor.execute(ExalateProcessor.java:73)
at com.exalate.processor.ExalateProcessor.executeProcessor(ExalateProcessor.java:46)
... 20 more
Caused by: javax.script.ScriptException: java.lang.NullPointerException: Cannot get property 'Remote Status RAX20' on null object
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:348)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:145)
... 23 more
Caused by: java.lang.NullPointerException: Cannot get property 'Remote Status RAX20' on null object
at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:57)
at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:168)
at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:44)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
at Script109.run(Script109.groovy:39)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:345)
... 24 more
Incoming sync data: Summary: bug multipleEntity Key: LAX20-225(id: 344880)Encoded payload: {"version":{"major":1,"minor":15,"patch":0},"hubIssue":{"components":[],"attachments":[],"voters":[],"customFields":{"ComponentA":{"id":14300.0,"name":"ComponentA","type":"OPTION","value":{"id":19031.0,"sequence":1.0,"value":"circle or SPC","disabled":false,"childOptions":[]}},"ComponentB":{"id":14301.0,"name":"ComponentB","type":"OPTION","value":{"id":19040.0,"sequence":0.0,"value":"APP","disabled":false,"childOptions":[]}},"Priority_HCP":{"id":10555.0,"name":"Priority_HCP","description":"","type":"OPTION","value":{"id":10675.0,"sequence":2.0,"value":"P3 (Low)","disabled":false,"childOptions":[]}},"Issue From":{"id":10560.0,"name":"Issue From","description":"Enter your account name. If issue from Support/Beta users, Kindly fill the ID Number field.","type":"OPTION","value":{"id":10712.0,"sequence":7.0,"value":"Beta","disabled":false,"childOptions":[]}}},"description":"test","project":{"id":17200.0,"key":"LAX20","name":"LAX20","lead":{"key":"fchua","active":true,"email":"Frederick.Chua@netgear.com","displayName":"Frederick Chua","username":"fchua"},"versions":[],"components":[]},"watchers":[],"fixVersions":[],"key":"LAX20-225","summary":"bug multiple","comments":[],"internalMap":{},"reporter":{"key":"pvenkatesh","active":true,"email":"Pokala.Venkatesh@netgear.com","displayName":"Venkatesh Pokala","username":"pvenkatesh"},"priority":{"id":"4","name":"Minor (P4)","description":"Minor loss of function, or other problem where easy workaround is present."},"labels":[],"customKeys":{},"workLogs":[],"issueType":{"id":"1","name":"Bug","description":"A problem which impairs or prevents the functions of the product."},"affectedVersions":[],"entityProperties":{},"status":{"id":"1","name":"OPEN","description":"The issue is open and ready for the assignee to start work on it.","category":{"id":2.0,"key":"new","name":"New"}}},"issueUrl":"https://njsdev.netgear.com/browse/LAX20-225"}
Script error for issue F6755-5. Details: Cannot get property 'Remote Status RAX20' on null object. Error line: Script109.groovy:39
Incoming script
if(firstSync && replica.project.key == "Dest1"){
issue.projectKey = "SOURCE"
issue.typeName = nodeHelper.getIssueType(replica.typeName)?.name ?: "Bug"
}
if(firstSync && replica.project.key == "SOURCE"){
issue.projectKey = "Dest1"
issue.typeName = nodeHelper.getIssueType(replica.typeName)?.name ?: "Bug"
}
if(replica.project.key == "Dest1"){
//sue.projectKey = "Dest2"
def statusMapping = ["New":"New", "OPEN":"OPEN", "To Be Fixed":"To Be Fixed", "Fixed":"Fixed", "CTS-Fixed":"CTS-Fixed", "Pending":"Pending", "Re-Open":"Re-Open"]
def remoteStatusName = replica.status.name
if (issue.project.key == "SOURCE") {
def remoteStatusDest1 = issue.customField."Remote Status Dest1".value
def remoteStatusDest2 = issue.customField."Remote Status Dest2".value
if (remoteStatusDest1 == "Rejected" && remoteStatusDest2 == "Rejected") {
issue.status = "Rejected"
}
if (remoteStatusDest1 == "Closed" && remoteStatusDest2 == "Closed") {
issue.status = "Closed"
}
}
issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
}
issue.summary = replica.summary
issue.description = replica.description
issue.labels = replica.labels
issue.comments = commentHelper.mergeComments(issue, replica)
issue.attachments = attachmentHelper.mergeAttachments(issue, replica)
issue.customFields."ComponentA".value = replica.customFields."ComponentA"?.value
issue.customFields."ComponentB".value = replica.customFields."ComponentB"?.value
issue.customFields."Issue From".value = replica.customFields."Issue From"?.value
issue.customFields."Priority_HCP".value = replica.customFields."Priority_HCP"?.value
issue.customFields."16001".value = replica.status.name
Please help me on this.
Thanks,
Venkatesh.
Francis Martens (Exalate) commented on 26 September 2020
The error message is
> Cannot get property āRemote Status RAX20ā on null object
The problem is on line 19 of your script. You should inspect it there.
Also your incoming script is using āissue.customFieldā. You should be careful as the customField array is named āissue.customFieldsā (with an s)
Please review
Venkatesh Pokala commented on 28 September 2020
Hi Francis Martens (Exalate),
Seems like iām closer now. Can you please me how to resolve the below error?
Cannot cast object 'OPEN' with class 'java.lang.String' to class 'com.exalate.api.domain.hubobject.v1_2.IHubStatus'. Error line: Script70.groovy:17
In coming script
if(firstSync && replica.project.key == "RAX20"){
issue.projectKey = "F6755"
issue.typeName = nodeHelper.getIssueType(replica.typeName)?.name ?: "Bug"
}
if(firstSync && replica.project.key == "F6755"){
issue.projectKey = "RAX20"
issue.typeName = nodeHelper.getIssueType(replica.typeName)?.name ?: "Bug"
}
//if(replica.project.key == "RAX20"){
//def remoteStatusName = replica.status.name
// def remoteStatusRAX20 = issue.customFields."Remote Status RAX20".value
//def remoteStatusLAX20 = issue.customFields."Remote Status LAX20".value
if (issue.project.key == "F6755") {
def remoteStatusRAX20 = issue.customFields."Remote Status RAX20".value
def remoteStatusLAX20 = issue.customFields."Remote Status LAX20".value
if (replica.status.name == "OPEN" && issue.customFields."Remote Status LAX20".value == "OPEN") {
issue.status = "OPEN"
}
}
issue.summary = replica.summary
issue.description = replica.description
issue.labels = replica.labels
issue.comments = commentHelper.mergeComments(issue, replica)
issue.attachments = attachmentHelper.mergeAttachments(issue, replica)
issue.customFields."ComponentA".value = replica.customFields."ComponentA"?.value
issue.customFields."ComponentB".value = replica.customFields."ComponentB"?.value
issue.customFields."Issue From".value = replica.customFields."Issue From"?.value
issue.customFields."Priority_HCP".value = replica.customFields."Priority_HCP"?.value
//issue.customFields."16001".value = replica.status.name
issue.customFields."Remote Status RAX20".value = replica.status.name
//issue.customFields."Remote Status LAX20".value = replica.status.name
Please help me
Juan Grases commented on 28 September 2020
Hi, the problem is on line:
issue.status = "OPEN"
it should be:
issue.setStatus("OPEN")
Take into account that setStatus is case sensitive, so it would probably rather be:
issue.setStatus("Open")
Venkatesh Pokala commented on 29 September 2020
Hi @Juan,
Thanks a ton. It is working as expected. One quick question, if I have multiple bugs with one source bug. Then I need to create a separate customfield for each connection?
Thanks,
Venkatesh.