Jelly was dropped in JIRA 6.4. Everything that could be done in Jelly could also be done in ScriptRunner.

Jelly Escalation

Typically Jelly was used for transitioning issues from a JQL query. This can be done with an Escalation Service instead, which is easier and more flexible than writing your code.

A direct translation of the examples given on the old jelly documentation page follows, using both Escalation Service and code.

Making an Issue Inactive

Using an Escalation Service
esc service1
In Code

If you want to do it code here’s how. It is rather long, mainly because of error handling around the transition.

You can set this up to run periodically by using a service.

When running any of these as a service, there is no authenticated user, so you cannot use ComponentAccessor.jiraAuthenticationContext. Instead you should get a user by name, as in the first example.
import com.atlassian.jira.bc.JiraServiceContextImpl
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.user.ApplicationUsers
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.workflow.JiraWorkflow
import com.opensymphony.workflow.loader.ActionDescriptor
import com.opensymphony.workflow.loader.StepDescriptor

def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def userUtil = ComponentAccessor.getUserUtil()
def issueService = ComponentAccessor.getIssueService()

////////////////////////////   CONFIGURATION ////////////////////////////
def workflowUser = "admin"          // user to run the query and do the transition as
def filterId = 10300                // filter ID
def actionName = "Mark Inactive"    // name of workflow action to execute

def comment = """
This issue has not been updated for 5 business days.

If you have an update, please use "Add Comments For Atlassian" action to let us know. If you need more time to gather information please let us know and we will 'freeze' this issue. If you have no other questions, please Close this issue.

If no update is received in the next 5 business days, this issue will be automatically closed.

Thank you,

  The Atlassian Support Team

def user = userUtil.getUserByKey(workflowUser)
assert user // can't find the user specified

def serviceContext = new JiraServiceContextImpl(user)
def directoryUser = ApplicationUsers.toDirectoryUser(user)

def searchRequest = searchRequestService.getFilter(serviceContext, filterId)
assert searchRequest: "No search for ID: ${filterId} - check it exists and permissions for ${}"

def query = searchRequest.query
def results =, user, PagerFilter.getUnlimitedFilter())

def getActionIdFromName = { Issue issue, String name ->
    JiraWorkflow workflow = ComponentAccessor.getWorkflowManager().getWorkflow(issue)
    StepDescriptor step = workflow.getLinkedStep(issue.statusObject)
    def actions = step.getActions()
    actions.addAll(workflow.getDescriptor().getGlobalActions() ?: [])
    def action = actions.find { ActionDescriptor ad -> == name }

results.getIssues().each { issue ->

    log.warn("Inactivating issue ${issue.key}")

    def issueInputParameters = issueService.newIssueInputParameters().setComment(comment)

    Integer actionId = getActionIdFromName(issue, actionName)
    if (actionId) {
        def validationResult = issueService.validateTransition(directoryUser,, actionId, issueInputParameters)

        if (validationResult.isValid()) {
            def issueResult = issueService.transition(directoryUser, validationResult)

            if (!issueResult.isValid()) {
                log.warn("Failed to transition subtask ${issue.key}, errors: ${issueResult.errorCollection}")
        } else {
            log.warn("Could not transition subtask ${issue.key}, errors: ${validationResult.errorCollection}")
    } else {"No action: $actionName found for issue: ${issue.key}")

Attaching files

There was an undocumented tag for attaching files.

<AttachFile key="JRA-1" filepath="/attachment/file/location/on/server"/>

This can be accomplished in ScriptRunner using the following equivalent code:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.AttachmentManager
import com.atlassian.jira.issue.attachment.CreateAttachmentParamsBean

def attachmentManager = ComponentAccessor.getComponent(AttachmentManager)
def user = ComponentAccessor.jiraAuthenticationContext.user
def issueManager = ComponentAccessor.issueManager

////////////////////////////   CONFIGURATION ////////////////////////////
def issue = issueManager.getIssueObject("JRA-333")
def filepath = "C:/tmp/star.png"

def file = new File(filepath)
assert file.exists() && file.canRead() : "Can't read file at ${filepath}"

def builder = new CreateAttachmentParamsBean.Builder(file,, "application/octet-stream", user, issue)


Creating Issues

You could define a Jelly Service to create issues. Here is code that will do the same in groovy:

import com.atlassian.jira.component.ComponentAccessor

def issueService = ComponentAccessor.issueService
def projectManager = ComponentAccessor.projectManager
def user = ComponentAccessor.jiraAuthenticationContext.getLoggedInUser()

def issueInputParameters = issueService.newIssueInputParameters()

issueInputParameters.with {
    projectId = projectManager.getProjectObjByKey("JRA").id
    summary = "Issue created from script"
    issueTypeId = "1"
    reporterId =

def validationResult = issueService.validateCreate(user, issueInputParameters)
assert !validationResult.errorCollection.hasAnyErrors()

def issueResult = issueService.create(user, validationResult) "Issue created: ${issueResult.issue}"

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.