Preparing for JIRA 6.1

Overview

This page is intended to be read by JIRA plugin developers to inform them of changes in JIRA 6.1 that could affect their plugins. JIRA users should consult the documentation here.

On this page:

About this page

Starting with JIRA 6.1, the purpose of this document has changed. It is now used to notify you as far in advance as possible of everything we know about that can possibly affect your plugins. Where possible, we will attach release targets.

You may need to update your plugin to work with JIRA 6.1

We have made changes to JIRA's stable (Java) API. For details on this, see the Clirr results. Also see our Java API policy for JIRA for technical information on the JIRA Java APIs and our approach to changing them. 

About the Early Access Program

The JIRA development team release an EAP milestone every two weeks for customers and plugin developers to keep abreast of upcoming changes. These EAP releases are available on the JIRA Early Access Program Downloads page.

(info) If you have any feedback for the 6.1 EAP releases, please use this issue: JRA-33146.

Summary of Changes

The risk level indicates the level of certainty we have that things will break if you are in the "Who is affected?" column and you don't make the necessary changes.

What is the change? When will this happen?* Risk level Who is affected? Details

New default JIRA workflow

  • 6.1-OD2 (OnDemand)
  • 6.1M2 (JIRA EAP)
LOW  

See New default JIRA workflow below.

Changes to the JIRAISSUE table in the database: New ISSUENUM column added and data removed from the PKEY column

  • 6.1-OD3 (OnDemand)

  • 6.1M3 (JIRA EAP)
HIGH

Anyone who interacts with JIRAISSUE.PKEY through direct JDBC or Generic Delegator.

See Database changes for the Edit Project Key feature below.

The email templates for JIRA have changed to sport a new ADG-compliant look and feel.

  • 6.1-OD3 (OnDemand)

  • 6.1M3 (JIRA EAP)
MEDIUM

Plugins that generate email notifications and use some (or all) of JIRA's core email templates.

See JIRA email template changes for details.

JIRA 6.1-OD3 will include AUI 5.1.1

  • 6.1-OD3 (OnDemand)

  • 6.1M3 (JIRA EAP)
LOW  

See AUI 5.1 Release Notes for details.

Custom Field Type changes

  • 6.1-OD3 (OnDemand)

  • 6.1M3 (JIRA EAP)
LOW

Plugins that provide new Custom Field Types

See Custom Field Types below.

Removal of JQL function "echo()"

  • 6.1-OD4 (OnDemand)
  • 6.1M4 (JIRA EAP)
LOW

Plugins that make use of the JQL function "echo()"

See this section below for details.

Active Objects upgraded to version 0.22.1

  • 6.1-OD6 (OnDemand)
  • 6.1M6 (JIRA EAP)
MEDIUM

Any plugin that uses Active Objects

See Active Objects upgrade to version 0.22.1 below.

New project-blueprint plugin module

  • 6.0.7
  • 6.1-OD6 (OnDemand)
  • 6.1M6 (JIRA EAP)
LOW

Any plugin that uses the project-template plugin module

See New project-blueprint plugin module below.

New JIRA Workflow Designer

  • 6.1M6 (JIRA EAP)

LOW

N/A

See Guide - JIRA workflow designer for details.

Issue Status as Lozenges

  • 6.2-OD4 (OnDemand)
LOW

All plugins that output issue statuses in their UI

See this section below for details.

Detailed Explanations of Changes

In this section:

New default JIRA workflow

In order to be able to start progress on an issue, a user must have the 'Assignable User' permission. When a user starts progress on an unassigned issue, the issue gets automatically assigned to that user. Similarly, any user with this permission can stop progress on an issue, although in this case the issue does not get reassigned to the user doing so.

This is different from the classic default JIRA workflow in the following ways:

  • Previously, when you started progress on an issue, it did not change the assignee to the current user. Whoever the assignee was at that time would remain as the issue's assignee.
  • In the classic default JIRA system workflow, only the issue assignee was able to execute the 'Start Progress' and 'Stop Progress' transitions. Now, as long as you have 'Assignable User' permission, you can execute this step.

Classic JIRA workflow available from Atlassian Marketplace

The classic default JIRA system workflow prior to this JIRA release is now available on Atlassian Marketplace.

If you import this workflow, you will need to add the 'Clear Resolution' post function back to the following three transitions:

  • Start Progress
  • Stop Progress
  • Reopen Issue

To add a new post function, see this procedure .

Database changes for the Edit Project Key feature

In JIRA 6.1, administrators will be able to update the project key (within certain constraints). See JRA-2703. Here are some important notes about the functional behaviour of this feature:

  • An instant project reindex will be triggered whenever the project key is updated.
  • It will not be possible to reuse keys that were previously used by a different project. However, it will be possible to switch back to an old project key that was associated with the project (e.g. if the administrator made a mistake).
  • The 'View Issue' and 'View Project' pages will redirect to the new URL, if someone browses to a URL with an old project key. This is the same behavior you see today when a JIRA issue key changes because you've moved the issue into a different project.

To implement this change, we have made a change to the entity model: The Issue object (jiraissue table in the database) has now a new property called number (issuenum column in the database). The number property contains the numerical part of the issue key and the issue key is now represented by the number and project properties, rather than the key property (pkey column).

You will be affected by this change differently, depending on how you were accessing data in JIRA:

  1. Via the Java API (no impact):
    • The relevant IssueService methods will continue to work as normal.
    • If the project key is changed, the ProjectManager.getProjectObjByKey() method will work with the new project key, as well as the old project key, if needed. If you only want to refer to a project by its current key, you can use ProjectManager.getProjectByCurrentKey() and ProjectManager.getProjectByCurrentKeyIgnoreCase(). This means that even plugins that store a project key in long term storage will probably continue to work. However, we recommend storing project ID as a safer alternative. Additionally, customer feedback may make us reconsider the position of not being able to re-use project keys.
  2. Via Ofbiz/EntityEngine (no impact for 6.X):
    • If you use GenericValues and access the Issue entity using the OfBizDelegator API, your code should still work as the key value is dynamically created. The OfBizDelegator will return IssueGenericValue, which is a special wrapper that translates project and number properties into the issue key. Note, we will deprecate this wrapper in JIRA 7.0.
    • If you use the GenericDelegator API you must transition to the OfBizDelegator API, as this will break because key will be missing.
    • Please be aware, if you change the project value in the Issue object it will instantly change issue key.
  3. Via JDBC:
    • The pkey column in the database has been obsoleted. When upgrading to JIRA 6.1 it will be emptied — you will first see this in the 6.1M3 milestone (6.1-OD3 for JIRA OnDemand). You will need to update your queries. If possible, we recommend that you transition to using the IssueService API instead.

      id summary pkey project ...
      3 Issue TES-1 10001  

      After change the issue will be stored in the database like:

      id summary pkey issuenum project ...
      3 Issue   1 10001  

Other considerations:

  • JQL: Project keys can now change, this means that old JQL queries can potentially stop working. This is not a new issue for JQL; for example, the same thing happens if you change a version name, a project name, a user's email address, etc. Plugins that automatically generate JQL based on project key should consider using the project ID instead if they want a value that cannot change. 
  • Lucene index: The Lucene index was not changed in any way, it will still store all the information it did in JIRA 6.0.
  • REST API calls will still work with old project key — REST calls that specify an issue key will work with the old issue key after the project key has changed. For example, /rest/api/issue/EXAMPLE-100 will still work after the project key is changed from EXAMPLE to DEMO.
  • We have created a new event, ProjectUpdatedEvent. This event is triggered any time a project's details are changed, including changing the project key.
  • If you need to retrieve all issue keys and project keys (historical and current), you can do this via the following:
    • REST:
      • Get all project keys for a project: /rest/api/2/project/<project key>?expand=projectKeys
    • Java API:
      • Get all project keys: com.atlassian.jira.project.ProjectManager#getAllProjectKeys
      • Get all issue keys for an issue: com.atlassian.jira.issue.IssueManager#getAllIssueKeys

Custom Field Types

Categories

Custom Fields Types can now be placed into one of 2 categories: STANDARD or ADVANCED. If you make no changes to your atlassian-plugin.xml file, your Custom Field Type will appear under the Advanced Category. We'd recommend leaving it in that category unless it's a commonly used type - in which case add it to the STANDARD category. If your Custom Field Type is there explicitly for your plugin to use behind-the-scenes (programatically) then we'd recommend hiding it from the UI by setting a managed-access-level of locked.

<customfield-type ... >
    ...
    <category>STANDARD</category>
    ...
</customfield-type>

Manage Access Levels

Custom Fields Types can aslo be given a "managed-access-level". You can set the access level to one of the following:

  • admin - custom fields of this type can be created by an admin or sysadmin. An additional label and message can be provided explaining special information about the type.
  • sysadmin - custom fields of this type can only be created by sysadmins only. An additional label and message can be provided explaining special information about the type.
  • locked - custom fields of this type can not be created via the UI. Use this if you're leveraging custom fields programatically via your plugin.

An example customfield declaration:

<customfield-type ...
                  managed-access-level="admin"
                  managed-description-key="customfield.special.textfield.managed.desc">
    ...
</customfield-type>

Preview images

A picture tells a thousand words. You can now add an image preview showing what your Custom Field Type might look like when used.

<customfield-type ... >
    ...
    <resource type="download" name="customfieldpreview.png" location="images/special-textfield-preview.png" />
    ...
</customfield-type>

Note:

The resource name must be customfieldpreview.png and the image 240×120 pixels in size (PNG recommended).

Removal of JQL function "echo()"

The echo() JQL function has been removed from JIRA. It was only used for testing and did not provide any value to users. If you have used this function in your code, you will need to remove it.


Active Objects plugin upgraded to version 0.22.1

The Active Objects plugin implements an ORM (object relational mapping) layer into Atlassian products, including JIRA (read more about Active Objects). This upgrade introduce the following changes that could potentially break your add-on:

New attributes on entity annotations

The OneToOne, OneToMany and ManyToMany annotations are used to define relationships in Active Objects. If you have used one of these to annotate a method as one end of a relationship, you can now set an attribute(s) that specifies the method on the remote end of the relationship. Previously, Active Objects would attempt to infer the method by the type, which did not work in all situations.

  • OneToOne and OneToMany annotations: New "reverse" attribute. Set this to the name of the corresponding getter on the remote interface.
  • ManyToMany annotation: New "reverse" and "through" attributes. Set the "reverse" attribute to the name of the corresponding getter on the intermediate interface. Set the "through" attribute to the name of the getter on the intermediate interface that refers to the remote interface.

You should start setting these attributes on your annotations now. If you do not set these attributes, Active Objects will revert to inferring the method by type. However, in a future upgrade, specifying these attributes will be required.

Active Objects no longer deletes tables and columns by default during migrations

Previously, when running an Active Objects migration (typically when your data model has changed), any tables corresponding with entities that were not declared got dropped. This meant that simple mistakes like leaving an entity class out of the manifest, out of a migration task, or downgrading the version of a plugin that uses ActiveObjects, resulted in irrecoverable data loss.

This is no longer the case. The ao.migrate method in Active Objects no longer deletes tables and columns by default. This method is used in upgrade tasks for an Active Objects.  The change to ao.migrate could break your plugin, for example, you may rely on ao.migrate "dropping" a certain column, as part of moving from a NULL ALLOWED to a NOT NULL constraint. In this case, your database will throw an error as the unwanted column will not be dropped.

If you relied on this behaviour, you must now use the ao.migrateDestructively() method instead, which behaves like ao.migrate() used to (i.e. will drop tables). The following sample code shows how you might use ao.migrateDestructively():

  Click here to view example...
    /**
     * A helper method to migrate from a class based Schema with replacements
     *
     * @param ao           the ActiveObject instance to call migrate on
     * @param schema       a class of AO entity declarations
     * @param replacements the replacement schema objects
     */
    public static void migrateDestructively(ActiveObjects ao, Class schema, Class<? extends RawEntity<?>>... replacements)
    {
        Class<? extends RawEntity<?>>[] schemaEntitiesWithReplacements = getSchemaEntitiesWithReplacements(schema, replacements);
        log.setLevel(Level.INFO);
        log.info(format("Migrating the following %d AO entities : ", schemaEntitiesWithReplacements.length));
        for (Class<? extends RawEntity<?>> entity : schemaEntitiesWithReplacements)
        {
            log.info(format("\tTable '%s' from '%s'", getTableName(entity), entity.getName()));
        }
        migrateDestructively(ao, schemaEntitiesWithReplacements);
    }
    private static void migrateDestructively(ActiveObjects ao, Class<? extends RawEntity<?>>[] schemaEntitiesWithReplacements)
    {
        Method migrateDestructively = getMigrateDestructively(ao, schemaEntitiesWithReplacements);
        if (migrateDestructively != null)
        {
            invokeMigrateDestructively(ao, schemaEntitiesWithReplacements, migrateDestructively);
        }
        else
        {
            ao.migrate(schemaEntitiesWithReplacements);
        }
    }
    private static Method getMigrateDestructively(ActiveObjects ao, Class<? extends RawEntity<?>>[] schemaEntitiesWithReplacements)
    {
        Method migrateDestructively;
        try
        {
            migrateDestructively = ao.getClass().getMethod("migrateDestructively", schemaEntitiesWithReplacements.getClass());
        }
        catch (NoSuchMethodException e)
        {
            log.info("No method migrateDestructively - will use ao.migrate()");
            migrateDestructively = null;
        }
        return migrateDestructively;
    }
    private static void invokeMigrateDestructively(ActiveObjects ao, Class<? extends RawEntity<?>>[] schemaEntitiesWithReplacements, Method migrateDestructively)
    {
        try
        {
            log.info("Invoking migrateDestructively");
            migrateDestructively.invoke(ao, new Object[]{schemaEntitiesWithReplacements});   // must prevent expansion into varargs
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException(e);
        }
        catch (InvocationTargetException e)
        {
            throw new RuntimeException(e);
        }
    }

Issue status rendering API

Infrastructure was introduced in to JIRA 6.1 that JIRA will take advantage of in JIRA 6.2 to render all issue statuses as lozenges.

(info) In JIRA 6.1, you do not need to migrate to rendering issue statuses as lozenges.

See JIRA issue statuses as lozenges for the full details.

New project-blueprint plugin module

Project template plugins were originally supported in JIRA 6.0 with the project-template module. However, JIRA 6.0.7 (and 6.1-OD6/6.1 EAPm6) introduce the project-blueprint plugin module. This module provides additional capabilities and is meant to supersede the project-template module. We strongly encourage you to use the project-blueprint module for project template plugin development.

See the new tutorial here: Tutorial - Creating a project template.

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport