How to delay third-party app startup to resolve dependency issues


Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.

Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

 

Summary

In some cases, a third-party application fails to start when Jira is starting because a dependency has yet to be loaded.

Usually, if the app starts successfully when enabled by using the UI, then we'd expect the procedure below to fix the issue.

Here, we'll detail how to delay a plugin startup to resolve this issue. Alternatively, the plugin developer is able to set this late startup in the atlassian-plugin.xml file (more details below).

Environment

Jira Server or Data Center.

Confluence Server or Data Center.

Diagnosis

A plugin fails to start when Jira starts up, but admins are able to enable it after Jira is available.

Errors in the logs may vary depending on the plugin, and might not always be obvious. Generally, these errors we're addressing here are caused by a lack of references to modules that should be loaded already, throwing NullPointerException or NoSuchMethodError, for example.

Cause

From Plugins2 add-ons developer documentation:

Even though your component's dependencies have been injected, this does not necessarily mean that those dependencies are in a "ready-to-use" state. For example, your component might depend on a JIRA component which caches information about add-ons. During your component's initialisation, there may still be other add-ons which have not yet been initialised, and thus enabled in the add-ons system. Therefore, accessing that JIRA component's methods will cause it to act without knowledge of other as-yet uninitialised add-ons. To avoid this scenario, it is best to defer accessing of dependencies which require knowledge of the add-on system until after all add-ons have been initialised and enabled. See the section on add-on system events below.

If initialisation fails for any reason, the add-on will effectively be disabled. Initialisation may fail if the component takes too long to complete (the default timeout is 30 seconds). Therefore, it is not a good idea to attempt any potentially long-running tasks during component initialisation, such as connecting to an external resource, or loading/processing large amounts of data. If such tasks are required but can be asynchronous, you could instead create a scheduled task to perform them at a more convenient time.

Attempting to access a component's dependencies during the initialisation stage can also lead to deadlocks. For example, if there happens to be a cyclic dependency between one component and another, and one accesses the other during initialisation, then the Spring container will get into a deadlock attempting to wait for both components to become initialised. After the timeout expires (as above), the container will realise that both components could not be initialised, and the loading of the plugin will fail.

Solution

(warning) Note that late startup happens after the node index rebuild. This means that apps that have indexed fields might end up with the last 24h if issues with fields missing from the index, depending on its implementation. We strongly recommend testing this type of solution in staging first.

Option 1 - app update

If the issue is recurring across different environments, the app developer can update the atlassian-plugin.xml file to let the plugin system know this app is set to a late startup.

<atlassian-plugin ...>
    <plugin-info>
        <!-- ... -->
        <startup>late</startup>
    </plugin-info>
</atlassian-plugin>

(info) Depending on the error during startup, the methods described in What is the best way to load a class or resource from a plugin? might also help.

Option 2 - override the app startup

To set a specific plugin to late startup:

  1. Identify the app key in Administration > Manage apps > Manage apps. For example:
  2. Create a file with the contents as below, replacing the app key by the desired app.
    We recommend the file to be placed in either the shared home or local home, and to be named something like pluginStartupOverrides.properties for easier reference.

    com.atlassian.labs.rest-api-browser=late
  3. Add the JVM argument below to Jira, with the appropriate file path:

    -Dcom.atlassian.plugin.manager.DefaultPluginManager.startupOverrideFile=/path/to/file/pluginStartupOverrides.properties
  4. Restart Jira;
  5. Repeat for each node.


Last modified on Nov 18, 2024

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.