[JIRA] Dev – Where are OSWorkflow Transition Screens?

Found a piece that isn’t well documented. But as usual, I’m explaining my steps and then the solution. It’s no real big deal anyway. 🙂

Here’s the background:
Mission was to write a Groovy script that returns all the transition screens used across all workflows of a given JIRA workflow scheme (for documentation purposes). This looked pretty easier, until a collection of ‘com.opensymphony.workflow.loader.ActionDescriptor’ came up without any linked JavaDocs. That looked like a dead end.

Then, with a little bit of googling I came across ActionDescriptor source code, which wasn’t helpful either. getView() method looked promising because ‘Transition View’ is a synonym used in JIRA UI for ‘Transition Screen’. But disappointingly it was just returning string ‘fieldscreen’ for every transition. Aw.. snap! 😦

Next attempt is called the ‘Bruteforce method’ (not java.lang.reflect.Method of course 😉 ).

Since I was too lazy to read across the ActionDescriptor’s source code:

// workflow is type of com.atlassian.jira.workflow.JiraWorkflow
// I'm not explaining all my code here
workflow.getAllActions().each {
  it.class.getDeclaredMethods().grep {
    it.name.matches( "^get.*" )
  }.each {
    log.debug ( it.name )

It didn’t took much of time. With a bit of guessing I made my first attempt with getter method ‘getMetaAttributes()’. And it had the eye-catching piece I was looking for!

workflow.getAllActions().each {
  log.debug ( it.getMetaAttributes().toString() )
[opsbar-sequence:10, jira.description:, jira.fieldscreen.id:10000]
[opsbar-sequence:20, jira.description:, jira.fieldscreen.id:20000]
[opsbar-sequence:40, jira.description:, jira.fieldscreen.id:30000]
[opsbar-sequence:60, jira.description:, jira.fieldscreen.id:30000]

getMetaAttributes() returns a HashMap. So, finally…

def screens = [:]
workflow.getAllActions().each {
  def screenId = it.getMetaAttributes()["jira.fieldscreen.id"]
  if ( screenId != "" ) {
    def workflowAction = workflow.name + " - " + it.name
    def workflowActions = []
    if ( screens[screenId] ) workflowActions = screens[screenId]
    workflowActions.add ( workflowAction )
    screens[screenId] = workflowActions
for ( e in screens ) {
  log.debug ( "Transition Screen: " + e.key )
  e.value.each {
    log.debug ( "  Workflow action: " + it )

Nice! This HashMap (‘screens’) is all what I wanted. 🙂 Each transition screen, and then where it has been used.

So one last thing… I also wanted to have a one last peek into ActionDescriptor’s source code on GitHub. Only the writeXML() method gave an indication that metaAttributes is actually a HashMap. There was absolutely no indication that screen association information is kept as a ‘meta attribute‘.

Bottom line(s):

  1. If you are a JIRA developer and whenever you want to find screens associated to a workflow, don’t use getView(). Use getMetaAttributes() and then look for the attribute with key “jira.fieldscreen.id”. In other words, transition screen is stored as a meta attribute in each transition. Screen is referred by its numeric ID as a string.
  2. Since OpenSymphony doesn’t seem to go away from JIRA, and some already claim that OpenSymphony is dead, it would be worthwhile if Atlassian maintains their own repository of OSWorkflow docs and special remarks.

[JIRA] Broken Permission Schemes?

Edit (24 May): Spoiler alert! There’s a better way.

I came across a corrupted JIRA database with all projects lost their permission schemes.

From the database, I believe this happens when corresponding records were deleted from the NODEASSOCIATION table. Whatever the cause is, you’ll notice the following log entry in atlassian-jira.log when this happens:

2017-05-23 02:57:18,363 WARN [permission.DefaultPermissionSchemeManager]: No permission scheme is associated with project ''

The problem is, (in JIRA 7.1.x) when you navigate to Project Administration –> Permissions to associate it with a scheme, you’ll see an empty page. For a newly created project Default Permission Scheme should show up, but now it absolutely has no permission scheme. It’s lost.

So, here’s the expensive but easy solution. Use the Script Runner add-on. Execute this Groovy code in the script console and it will fix everything in a minute!

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.bc.project.ProjectService;
import com.atlassian.jira.bc.project.ProjectService.UpdateProjectSchemesValidationResult;

def projectService = ComponentManager.getComponent(ProjectService.class);
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();

Long permissionSchemeId = 10000; // ID of the permission scheme that you wish to associate to each project
Long notificationSchemeId = null;
Long issueSecuritySchemeId = null;
ProjectService.UpdateProjectSchemesValidationResult validationResult = projectService.validateUpdateProjectSchemes(currentUser, permissionSchemeId, notificationSchemeId, issueSecuritySchemeId);

ComponentAccessor.getProjectManager().getProjectObjects().each {
  projectService.updateProjectSchemes(validationResult, it);

As it can be understood from the code, you can fix Notification Schemes and Issue Security Schemes using the same way.