[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 )
  }
}
getAutoExecute
getConditionalResults
getPreFunctions
getUnconditionalResult
getMetaAttributes
getValidators
getPostFunctions
getRestriction
getView
getName

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] Lexorank integrity issues?

So, this is loosely another part of the unofficial series ‘fixing a corrupted JIRA db‘.

However, this is a different case. This JIRA instance (7.1.x) was created by importing a huge XML backup (> 1 million issues). Due to an unknown reason, ActiveObjects didn’t import. That means, JIRA Software (aka JIRA Agile) no longer functioned normal.

It was soon discovered that Lexorank integrity checks fail. For the record, following integrity checks failed:

Marker rows present in table for rank field
Marker rows correctness check
Marker rows in valid bucket check
Issue rows in valid bucket check
Balance status check

Now what? I made an unsuccessful attempt of uninstalling JIRA Software, then dropping all database tables/ triggers/ sequences with the prefix AO_60DB71_ and then re-installing JIRA Software. This didn’t help.

Then, I wanted to study the under-the-hood stuff of Lexorank management. I already knew of two database tables involved, AO_60DB71_LEXORANK and AO_60DB71_LEXORANKBALANCER.

First I created a custom field of type ‘Global Rank’ and named it ‘Rank2’.

Then, I navigated to JIRA Administration –> System –> Lexorank management. Now I could see two Rank fields under the Balancing section. I balanced them once again and executed the integrity checks. The old one still failed the above checks, but the new one passed all checks!

Now, let’s take a look at the database. Following query returned two rows, that looked like an upper marker (1|zzzzzz:) and a lower marker (1|000000:). Both were associated with the field ID of the newly created ‘Rank2’ custom field.

select * from AO_60DB71_LEXORANK;

What I did was a very simple thing. I updated the field ID of the two records so they are now associated to the old Rank field.

update AO_60DB71_LEXORANK
set FIELD_ID = (select ID from CUSTOMFIELD where CFNAME = 'Rank');

commit;

Finally, to clean up I deleted the newly created Rank2 custom field. Simple!

After a JIRA restart Lexorank started to function normal, with all the integrity checks passed. I hope my approach will help someone who has run into the same problem.

[JIRA] Broken Permission Schemes? (better way)

Yesterday I blogged about how to fix JIRA Permission Schemes of a corrupted JIRA database. The observation was from atlassian-jira.log, but in my case I soon found out the problem was much greater in my case.

All projects lost their workflow scheme, issue type screen scheme, and field configuration scheme, and project category associations. This led me to peek into the database directly. The NODEASSOCIATION table had only 20 – 30 rows – those are the permission schemes I fixed yesterday. Also, all issues lost their components, affected versions and fix versions.

So how do I fix this? I can fix issue type screen scheme association without a hassle, notification schemes without a hassle, but workflow schemes? Even automating the restoration may run into dead ends given the nature of steps of workflow scheme association through UI. The only option seemed to be restore the corresponding records to NODEASSOCIATION table from the most recent database backup.

This is actually safer than meddling with other database tables in JIRA, because NODEASSOCIATION has no primary key, so no chance of primary key violation errors after starting up JIRA. With all sounded good, here’s my steps.

  1. From the most recent backup of the same JIRA instance, export the NODEASSOCIATION table. With Oracle SQL Developer there’s an option to export records in ‘INSERT’ format, which generates a SQL script.
    • If you use another database/ client that can’t export into ‘INSERT’ format, you can export to a CSV or spreadsheet and then use spreadsheet formulae to generate INSERT queries.
    • In my case I had to exclude where SINK_NODE_ENTITY = ‘PermissionScheme’ because I’ve already fixed that.
  2. In the target JIRA database, run the above SQL script and commit. Easy! 😀
  3. Restart JIRA and re-index.

This added some 60,000+ records with all entity association you’ll find out with this query:

select distinct source_node_entity, sink_node_entity, association_type from nodeassociation order by 1 asc;

That’s it! Not 100%, but this worked up to my expectation. The key reason for this being hassle-free and easy is, NODEASSOCIATION table has no primary key. This is actually much much better than using Groovy, because you have to pay for the add-on. 🙂

[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.

Wunderlist for Ubuntu

Wunderlist killed its app for Ubuntu long time back.

And then it was bought by Microsoft, so I hardly think there will be a Linux app ever again. For a long time I didn’t use Wunderlist, but I thought of giving it a try once again. I figured out that pinning Wunderlist tab on Firefox works to some extent.

Today I was installing new software on my new Ubuntu installation, and figured out Atlassian HipChat is now ‘hipchat4’. The new hipchat4 is not the same as old app, but just the web app launched in a lightweight web browser. It’s the same way that Amazon app works (I’d love to use it but they don’t ship to Sri Lanka 😦 ). Can’t this also be working for Wunderlist?

So here’s what I did:

$ gedit ~/.local/share/applications/wunderlist.desktop

And here’s the file contents (in fact, I copied this from an existing .desktop file and changed several lines 😉 ).

[Desktop Entry]
Version=1.0
Name=Wunderlist
GenericName=Wunderlist
Comment=Wunderlist Task Management Tool
Keywords=Tasks;Tasklist;Wunderlist;TODO;
Type=Application
Icon=/opt/wunderlist/icon.png
Exec=webapp-container --enable-media-hub-audio "https://www.wunderlist.com/webapp#/lists/today" --maximized
Terminal=false
Categories=Accessories;Office;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;
X-Ubuntu-Touch=true
X-Ubuntu-Gettext-Domain=webapp-container
X-Ubuntu-Single-Instance=true
X-Ubuntu-Default-Department-ID=web-browsers
X-Screenshot=/opt/wunderlist/screenshot.png
X-Ubuntu-Splash-Color=#FFFFFF

Find a Wunderlist icon and a screenshot using Google image search, and copy them to /opt/wunderlist.

$ sudo mkdir /opt/wunderlist
$ sudo mv icon.png screenshot.png /opt/wunderlist/

Hit Super Key and type Wunderlist (perhaps you may need to log out and log in again to make it appear for the first time). Launch Wunderlist and log in. Right click the Wunderlist icon on Unity launcher and click ‘Lock to Launcher’.

That’s it!

Desktop notifications and audible bell are also working, but file upload isn’t working with this.