Remote Events - BETA
A standard event listener allows you to listen for and respond to events that occur in the current application. Remote events allow you to listen for events in a linked Bitbucket, JIRA or Confluence instance. Bamboo will be available soon.
Examples of possible usage include:
-
Provisioning - when a project is created in JIRA, create it also in Bitbucket and Confluence.
-
Synchronise JIRA versions between instances - when you create a version in one JIRA instance it appears in another
-
When a JIRA version is created, automatically create a page in Confluence
When setting up a remote listener, you will select the linked application, then choose one or more events to handle. Under the covers, when the event is fired on the remote application, it will be serialised to JSON, then sent to the receiving instance. Upon arrival it’s republished as a local event and your listener will then respond to it.
It’s important to note that the event received is just a Map
, and not the same type of event that you would get if it you were responding to a local event. The best way to start with remote events is to set up the remote listener, then log the event you get:

Select the application link which points to the application that you wish to receive events from. For the purposes of this example, we will receive an event from Bitbucket, but it doesn’t matter which event or which application you are using, the same technique applies:

The code sample above is the following. It simply dumps the content of the event to the log.
import groovy.json.JsonOutput
log.info "Remote event received: "
log.debug JsonOutput.prettyPrint(JsonOutput.toJson(event))
Note on app link configuration.
If you have not configured OAuth (Impersonation), you may be prompted to authorize communication to the remote app in order to retrieve the list of events, on your behalf. Upon submitting the form, the remote app will contact the app you are working on, to verify it can send the event as the user that initiated the event. If you are not using OAuth (Impersonation), you should specify a user that will send the events. We discuss getting the actual user that initiated the event later. It’s a good idea to create a user called for example |
To test the handler, we will cause the event to be fired on the remote application, in this case by creating a new repository in Bitbucket.
If everything is set up correctly, on JIRA you should see in your logs something like the following:
{
"actor": {
"active": true,
"displayName": "Mr Admin",
"emailAddress": "admin@example.com",
"name": "admin",
},
"date": "2017-07-27T20:18:36+0000",
"eventClass": "com.atlassian.bitbucket.event.repository.RepositoryCreatedEvent",
"repository": {
"forkable": true,
"id": 14,
"name": "thing",
"project": {
"id": 1,
"key": "TEST",
"name": "TEST",
"public": false,
"type": "NORMAL"
},
},
"uuid": "0979b03b-afb6-464c-bc91-274dac63f937"
}
// some properties omitted
So, the event
object is a Map with the properties above. To get the repository name you would use:
assert event.repository.name == "thing"
The project key for this repository:
assert event.repository.project.key == "TEST"
The user name that initiated this event on the remote system:
assert event.actor.name == "admin"
If using OAuth (Impersonation), and you have not specified a user to send events as, the current user when receiving the remote event will be the user that initiated the remote event. You can get that user in the normal way for your application, eg on JIRA:
If you have specified a user, you can get the remote user name using |
Example: Synchronize JIRA Versions
In this example we have two JIRA instances linked togther. We’ll assume that there is at least one like-named project on both instances.
When the create version event arrives we will simply create a version in the same project on the local instance.
import com.atlassian.jira.bc.project.version.VersionBuilderImpl
import com.atlassian.jira.bc.project.version.VersionService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.datetime.DateTimeFormatterFactory
import com.atlassian.jira.datetime.DateTimeStyle
import groovy.json.JsonOutput
def versionService = ComponentAccessor.getComponent(VersionService)
def user = ComponentAccessor.jiraAuthenticationContext.getLoggedInUser()
def projectManager = ComponentAccessor.projectManager
log.info "Remote event received: "
log.debug JsonOutput.prettyPrint(JsonOutput.toJson(event)) (1)
def dateTimeFormatterFactory = ComponentAccessor.getComponent(DateTimeFormatterFactory)
def systemTimeZoneFormatter = dateTimeFormatterFactory.formatter().withStyle(DateTimeStyle.DATE).withSystemZone()
if (event.version.projectId == 10000) {
def versionBuilder = new VersionBuilderImpl()
.projectId(projectManager.getProjectObjByKey("JRA").id) // project key on receiving instance
.name(event.version.name)
.description(event.version.description)
def userStartDate = event.version.userStartDate as String
if (userStartDate) {
versionBuilder.startDate(systemTimeZoneFormatter.parse(userStartDate))
}
def userReleaseDate = event.version.userReleaseDate as String
if (userReleaseDate) {
versionBuilder.releaseDate(systemTimeZoneFormatter.parse(userReleaseDate))
}
def validationResult = versionService.validateCreate(user, versionBuilder)
if (validationResult.isValid()) {
versionService.create(user, validationResult)
}
else {
log.warn ("Could not create version: " + validationResult.errorCollection)
}
}
1 | Dump the json representation for debugging purposes |
Most of this code relates to the fact that we don’t receive the dates as a Date
class, so we need to parse them out. Dumping the event
map will show you exactly what you are getting. See the documentation on remote events for an alternative way of accomplishing this.
For how-to questions please ask on Atlassian Answers where there is a very active community. Adaptavist staff are also likely to respond there.
Ask a question about ScriptRunner for JIRA, for for Bitbucket Server, or for Confluence.