The Exalate team will be on holiday for the coming days - returning Jan 4
Enjoy & stay safe

Can't get sprint sync to trigger from Jira Server to Jira Cloud

 
2
1
0

Trigger is set up for Sprint - there is no configuration paramater, so it should trigger on all sprint updates.

Outgoing script is below.

Trigger is enabled, and we update the goal in an existing sprint, and there is nothing in outgoing sync queue or in the log indicating that it tried to synch anything.  

If we do a bulk exalate from the sprint trigger, it racks up about 300 nullpointer exceptions related to all kinds of issues.  Maybe it is also hitting a different trigger for issues - it's hard to tell.

Is there any way to verify that this script is getting called from the updated Sprint object?



Outgoing script:

if(entityType == "sprint" && sprint.originBoardId == "107" && (sprint.id == "321" || sprint.id == "326" )){

    //Only sync sprints on board 107 and sprints on or after sprint 19 (id >= 321)

    replica.name = sprint.name

    replica.goal = sprint.goal

    replica.state = sprint.state

    replica.startDate = sprint.startDate

    replica.endDate = sprint.endDate

    replica.originBoardId = sprint.originBoardId

}

if(entityType == "issue"){

   //Executed when syncing an issue to a remote side

   replica.summary = issue.summary

   replica.description = issue.description

   replica.project = issue.project

   replica.type = issue.type

    //....

    //other script rules to sync issues

    //sprint....

   replica.customFields.Sprint = issue.customFields.Sprint

   replica.key            = issue.key

   replica.type           = issue.type

   replica.assignee       = issue.assignee

   replica.reporter       = issue.reporter

   replica.summary        = issue.summary

   replica.description    = issue.description

   replica.labels         = issue.labels

   replica.comments       = issue.comments

   replica.resolution     = issue.resolution

   replica.status         = issue.status

   replica.parentId       = issue.parentId

   replica.priority       = issue.priority

   replica.attachments    = issue.attachments

   replica.project        = issue.project

   replica.customFields."Story Points" = issue.customFields."Story Points"

   SubTask.send()

   // Ensure that the Epic is synced first, such that stories sent later can be associated to the right epic

   Epic.sendEpicFirst()

}

//Comment these lines out if you are interested in sending the full list of versions and components of the source project.

replica.project.versions = []

replica.project.components = []

  1. Ariel Aguilar

    Hi Eric,

    We see you have on your script:

    SubTask.send()

    Do you have the external script properly added as per:

    https://docs.idalko.com/exalate/x/RQaOAQ?
    Also, there is:

    Epic.sendEpicFirst()

    Same case, do you have the external script already added as per:

    https://docs.idalko.com/exalate/x/9ICKAg?

    Kind regards,

    Ariel

  2. Eric Hilfer

    Epics and subtasks are sync'ing correctly - here is the incoming script on the external Jira Cloud side:



    // Sprints
    //entityType represent the type of the remote side entity
    if(entityType == "sprint"){
        //Executed when receiving a sprint sync from the remote side
        def sprintMap = ["107":"4"] //[remoteBoardId: localBoardId]
         
        sprint.name = replica.name
        sprint.goal = replica.goal
        sprint.state = replica.state
        sprint.startDate = replica.startDate
        sprint.endDate = replica.endDate
        def localBoardId = sprintMap[replica.originBoardId]
        if(localBoardId == null){
           throw new com.exalate.api.exception.IssueTrackerException("No board mapping for remote board id "+replica.originBoardId)
        }
        sprint.originBoardId = localBoardId //Set the board ID where the sprint will be created
    }
    if(entityType == "issue"){
        //Executed when receiving an issue sync from the remote side
        if(firstSync){
            issue.projectKey   = "JAN" 
            if(replica.parentId){
                issue.typeName     = "Sub-task" //Make sure to use the right subtask type here.
                def localParent = nodeHelper.getLocalIssueFromRemoteId(replica.parentId.toLong())
                if(localParent){
                    issue.parentId = localParent.id
                } else {
                    throw new com.exalate.api.exception.IssueTrackerException("Subtask cannot be created: parent issue with remote id " + replica.parentId + " was not found. Please make sure the parent issue is synchronized before resolving this error" )
                }


            }

            // Set type name from source issue, if not found set a default
            issue.typeName     = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "Sub-task"
                
            
        }
        //....
        //other script rules to sync issues
        issue.summary      = replica.summary
        issue.description  = replica.description
        // issue.comments     = commentHelper.mergeComments(issue, replica)
        issue.attachments  = attachmentHelper.mergeAttachments(issue, replica)
        issue.labels       = replica.labels

        /*
        User Synchronization (Assignee/Reporter)

        Set a Reporter/Assignee from the source side, if the user can't be found set a default user
        You can use this approach for custom fields of type User
        */
        def defaultUser = nodeHelper.getUserByEmail("default@idalko.com")
        issue.reporter = nodeHelper.getUserByEmail(replica.reporter?.email) ?: defaultUser
        issue.assignee = nodeHelper.getUserByEmail(replica.assignee?.email) ?: defaultUser

        
        /*
        Status Synchronization

        Sync status according to the mapping [remote issue status: local issue status]
        If statuses are the same on both sides don't include them in the mapping
        */
        def statusMapping = ["BA Review":"UAT"]
        def remoteStatusName = replica.status.name
        issue.setStatus(statusMapping[remoteStatusName] ?: remoteStatusName)
        
        /*
        Custom Fields

        This line will sync Text, Option(s), Number, Date, Organization, and Labels CFs
        For other types of CF check documentation
        issue.customFields."CF Name".value = replica.customFields."CF Name".value
        */
        issue.customFields."Story Points"?.value = replica.customFields."Story Points".value
        
        /*
        Comment Synchronization

        Sync comments with the original author if the user exists in the local instance
        Remove original Comments sync line if you are using this approach
        */
        issue.comments = commentHelper.mergeComments(issue, replica){ it.executor = nodeHelper.getUserByEmail(it.author?.email) }
     
        
        //....
        def remoteSprintId = replica.customFields.Sprint?.value?.find { it.state.toUpperCase() != "CLOSED" }?.id
        if(remoteSprintId){
           def localSprintId = nodeHelper.getLocalIssueKeyFromRemoteId(remoteSprintId, "sprint")?.id
             if(localSprintId){
                issue.customFields.Sprint.value = localSprintId
            }
        }
        // Epics    
        // should be at the end of the incoming sync  script
        Epic.receive()
    }


  3. Eric Hilfer

    To help with debugging, I added the following lines to the on-prem outgoing rules script at the beginning:


    log.info("entityType: "+ entityType)

    if(entityType == "sprint"){

        log.info("sprint.originBoardId: "+  sprint.originBoardId)

        log.info("sprint.id: "+  sprint.id)

        log.info("sprint.name: "+  sprint.name)

    }


    And we turned on debug logging on the on-prem Jira as described here: 

    https://docs.idalko.com/exalate/display/ED/Jira+on-premise%3A+How+to+enable+debug+logging


    But, I am not seeing any of my info messages in the exalate.log file, even though some issues have been processed and another attempt was made to update the sprint object on board 107 with sprint id 326.  Are we doing something wrong with the logging setup, or looking in the wrong log file?



  4. Eric Hilfer

    Update: the logging info was actually going into the attlasian-Jira log - we were looking in the wrong place.

  5. Eric Hilfer

    The log info indicates a script error related to trying to apply "versions" to the sprint object.


    2021-06-24 20:53:05,899+0000 pool-153-thread-1 INFO sburkhart 1162x553072x1 pfcu7y 71.184.147.4,172.17.20.137,127.0.0.1 /secure/ExalateIssueOperation.jspa [com.exalate.script] Executing the data filter for the issue `326`, connection `Argos_to_Unicon`
    2021-06-24 20:53:05,941+0000 pool-153-thread-1 INFO sburkhart 1162x553072x1 pfcu7y 71.184.147.4,172.17.20.137,127.0.0.1 /secure/ExalateIssueOperation.jspa [com.exalate.script] entityType: sprint
    2021-06-24 20:53:05,941+0000 pool-153-thread-1 INFO sburkhart 1162x553072x1 pfcu7y 71.184.147.4,172.17.20.137,127.0.0.1 /secure/ExalateIssueOperation.jspa [com.exalate.script] sprint.originBoardId: 107
    2021-06-24 20:53:05,941+0000 pool-153-thread-1 INFO sburkhart 1162x553072x1 pfcu7y 71.184.147.4,172.17.20.137,127.0.0.1 /secure/ExalateIssueOperation.jspa [com.exalate.script] sprint.id: 326
    2021-06-24 20:53:05,941+0000 pool-153-thread-1 INFO sburkhart 1162x553072x1 pfcu7y 71.184.147.4,172.17.20.137,127.0.0.1 /secure/ExalateIssueOperation.jspa [com.exalate.script] sprint.name: PMP Sprint 20
    2021-06-24 20:53:05,944+0000 pool-153-thread-1 ERROR sburkhart 1162x553072x1 pfcu7y 71.184.147.4,172.17.20.137,127.0.0.1 /secure/ExalateIssueOperation.jspa [c.e.r.out.schedule.EventSchedulerService] Could not create a replica for issue 326 because of a script error
    com.exalate.api.exception.script.ScriptException: Cannot set property 'versions' on null object
            at com.exalate.error.services.ScriptExceptionCategoryService.categorizeProcessorAndIssueTrackerExceptionsIntoScriptExceptions(ScriptExceptionCategoryService.scala:38)
            at com.exalate.processor.ExalateProcessor.executeProcessor(ExalateProcessor.java:57)
            at com.exalate.processor.jira.JiraCreateReplicaProcessor.executeDataFilter(JiraCreateReplicaProcessor.java:312)
            at com.exalate.processor.jira.JiraCreateReplicaProcessor.createHubReplica(JiraCreateReplicaProcessor.java:189)
            at com.exalate.replication.out.schedule.EventSchedulerService$1.call(EventSchedulerService.java:166)
            at com.exalate.replication.out.schedule.EventSchedulerService$1.call(EventSchedulerService.java:163)
            at com.exalate.replication.out.schedule.EventSchedulerService.schedulePairEventInternal(EventSchedulerService.java:196)
            at com.exalate.replication.out.schedule.EventSchedulerService.schedulePairEvent(EventSchedulerService.java:163)
            at com.exalate.replication.out.schedule.EventSchedulerServiceLockAware.schedulePairEvent(EventSchedulerServiceLockAware.java:77)
            at com.exalate.replication.out.eventhandler.IssueEventHandlerService.handleTriggers(IssueEventHandlerService.java:284)
            at com.exalate.replication.out.eventhandler.IssueEventHandlerService.handleEvent(IssueEventHandlerService.java:176)
            at com.exalate.replication.out.eventhandler.IssueEventHandlerService.handleSprintEvent(IssueEventHandlerService.java:155)
            at com.exalate.replication.out.eventhandler.sprint.SprintEventHandlerTask.run(SprintEventHandlerTask.java:42)
            at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
            at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
            at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
            at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
            at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
            at java.base/java.lang.Thread.run(Thread.java:834)
    Caused by: javax.script.ScriptException: javax.script.ScriptException: java.lang.NullPointerException: Cannot set property 'versions' on null object
            at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:158)
            at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
            at com.exalate.processor.ExalateProcessor.execute(ExalateProcessor.java:98)
            at com.exalate.processor.ExalateProcessor.executeProcessor(ExalateProcessor.java:55)
            ... 17 more
            at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320)
            at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:155)
            ... 20 more
    Caused by: java.lang.NullPointerException: Cannot set property 'versions' on null object
            at org.codehaus.groovy.runtime.NullObject.setProperty(NullObject.java:80)
            at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:213)
            at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setProperty(ScriptBytecodeAdapter.java:496)
            at Script10.run(Script10.groovy:46)
            at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317)

  6. Eric Hilfer

    Moving the versions and components line fixed the synch issue (but not the bulk exalate errors)

    if(entityType == "sprint"){
        log.info("entityType: "+ entityType)
        log.info("sprint.originBoardId: "+  sprint.originBoardId)
        log.info("sprint.id: "+  sprint.id)
        log.info("sprint.name: "+  sprint.name)
    }
    if(entityType == "sprint" && sprint.originBoardId == "107" && (sprint.id == "321" || sprint.id == "326" )){
        //Only sync sprints on board 107 and sprints on or after sprint 19 (id >= 321)
        replica.name = sprint.name
        replica.goal = sprint.goal
        replica.state = sprint.state
        replica.startDate = sprint.startDate
        replica.endDate = sprint.endDate
        replica.originBoardId = sprint.originBoardId
    }
    if(entityType == "issue"){
       //Executed when syncing an issue to a remote side
       replica.summary = issue.summary
       replica.description = issue.description
       replica.project = issue.project
       replica.type = issue.type
        //....
        //other script rules to sync issues
        //sprint....
       replica.customFields.Sprint = issue.customFields.Sprint
       replica.key            = issue.key
       replica.type           = issue.type
       replica.assignee       = issue.assignee
       replica.reporter       = issue.reporter
       replica.summary        = issue.summary
       replica.description    = issue.description
       replica.labels         = issue.labels
       replica.comments       = issue.comments
       replica.resolution     = issue.resolution
       replica.status         = issue.status
       replica.parentId       = issue.parentId
       replica.priority       = issue.priority
       replica.attachments    = issue.attachments
       replica.project        = issue.project
       replica.customFields."Story Points" = issue.customFields."Story Points"
       SubTask.send()
       // Ensure that the Epic is synced first, such that stories sent later can be associated to the right epic
       Epic.sendEpicFirst()
       //Comment these lines out if you are interested in sending the full list of versions and components of the source project.
       replica.project.versions = []
       replica.project.components = []
    }
    /*
    Custom Fields
    replica.customFields."CF Name" = issue.customFields."CF Name"
    */
CommentAdd your comment...

1 answer

  1.  
    2
    1
    0

    I had to move the versions and components assignment lines into the if block for "issues" entityTypes instead of letting it get hit for "sprints" entityTypes, too.
    When we bulk exalate the sprints trigger, it still throws a few hundred nullpointer exceptions, but the sprint did synch up this time.

    1. Francis Martens (iDalko)

      On what side are you getting this nullpointer exception?

    2. Eric Hilfer

      On the Jira server outgoing side

    3. Eric Hilfer

      And the only way to clear those errors is to go directly into the database and truncate the errors table

    4. Francis Martens (iDalko)

      Hi Eric Hilfer 
      According to the ticket - the problem has been addressed - please confirm

    5. Eric Hilfer

      We were shown  a work around to truncate the errors table so we are able to operate, but the  problem of approximately 300 nullpointer execptions that get thrown when trying to bulk exalate the sprints trigger has not been resolved. We will just avoid trying to perform a bulk exalate. 

    CommentAdd your comment...