Jira plugin migrate webhooks

Hello all,

I want to migrate webhooks to different JSM instances. And I’ve add the following packages to my pom.xml.


Below is part of the code to export webhooks(the import lines, the class initialization and the simplified code to just return the name of one of the webhooks)

import com.atlassian.jira.web.bean.TaskDescriptorBean;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.atlassian.jira.plugins.webhooks.store.JiraWebHookListenerStore;
import com.atlassian.webhooks.api.register.listener.PersistentWebHookListener;

public Exporter(
    @Named("jiraWebHookListenerStore") final JiraWebHookListenerStore jiraWebHookListenerStore
) {
    this.jiraWebHookListenerStore = jiraWebHookListenerStore;

public Response exportProjectConfiguration() throws Exception {
    try {
        String name = "";
        Collection<PersistentWebHookListener> webhooks = jiraWebHookListenerStore.getAllWebHooks();
        for (PersistentWebHookListener webhook: webhooks) {
            name = webhook.getName();
        return Response.ok(new ExporterModel(name)).build();
    catch (Exception e) {   
        throw e;

After I’ve compiled the plugin and started the Jira system, the error message is the following:

[INFO] [talledLocalContainer]
[INFO] [talledLocalContainer]     2 plugins failed to load during Jira startup.
[INFO] [talledLocalContainer]
[INFO] [talledLocalContainer]           'com.morganstanley.ai.jira-workflow-migrator' - 'jira-workflow-migrator'  failed to load.
[INFO] [talledLocalContainer]                   Cannot start plugin: com.morganstanley.ai.jira-workflow-migrator
[INFO] [talledLocalContainer]                           Unable to resolve com.morganstanley.ai.jira-workflow-migrator [189](R 189.0): missing requirement [com.morganstanley.ai.jira-workflow-migrator [189](R 189.0)] osgi.wiring.package; (osgi.wiring.package=com.atlassian.jira.plugins.webhooks.store) Unresolved requirements: [[com.morganstanley.ai.jira-workflow-migrator [189](R 189.0)] osgi.wiring.package; (osgi.wiring.package=com.atlassian.jira.plugins.webhooks.store)]
[INFO] [talledLocalContainer]
[INFO] [talledLocalContainer] Nov 25, 2022 8:43:28 PM org.apache.catalina.startup.HostConfig deployWAR
[INFO] [talledLocalContainer] INFO: Deployment of web application archive [C:\Users\yaoqih\Projects\jira-workflow-migrator\target\container\tomcat8x\cargo-jira-home\webapps\jira.war] has finished in [153,914] ms
[INFO] [talledLocalContainer]                   It was loaded from C:\Users\yaoqih\Projects\jira-workflow-migrator\target\jira\home\plugins\installed-plugins\jira-workflow-migrator-1.0.0-SNAPSHOT.jar
[INFO] [talledLocalContainer] Nov 25, 2022 8:43:28 PM org.apache.catalina.startup.HostConfig deployDirectory
[INFO] [talledLocalContainer] INFO: Deploying web application directory [C:\Users\yaoqih\Projects\jira-workflow-migrator\target\container\tomcat8x\cargo-jira-home\webapps\host-manager]
[INFO] [talledLocalContainer]
[INFO] [talledLocalContainer]           'com.morganstanley.ai.jira-workflow-migrator-tests' - 'jira-workflow-migrator'  failed to load.

Please kindly help me on this issue.

Yaoqi Huang

The error message is telling you that the jira-workflow-migrator plugin thinks it needs the com.atlassian.jira.plugins.webhooks.store package, but at runtime, that package turns out to not be available from OSGi.

The jira-workflow-migrator plugin is asking for that package because its code contains a reference to JiraWebHookListenerStore, which lives in that package. The reason the package is not available from OSGi is that the jira-webhooks-plugin, which contains that package, does not export it to OSGi. So the upshot of all this is that it’s not possible for your plugin to load the JiraWebHookListenerStore class at runtime.

Luckily for you, the fix is simple: change the Exporter constructor to inject a com.atlassian.webhooks.spi.WebHookListenerStore instead of a JiraWebHookListenerStore. This will compile because WebHookListenerStore comes from the atlassian-webhooks-api Maven artifact that you already have as a dependency.

If you attach a debugger to your constructor, you will observe that the injected WebHookListenerStore actually is a proxy to the JiraWebHookListenerStore, but your plugin doesn’t need to know or care about that. It only needs an implementation of WebHookListenerStore in order to call getAllWebHooks() on it.

This also means that you can remove your dependency on the jira-webhooks-plugin. Not only don’t you need it, but it’s actually a bad idea to depend (in a Maven sense) upon a plugin artifact, because doing so will drag in a whole raft of transitive dependencies that are nothing to do with the problem you are trying to solve. It’s best to stick to API artifacts like atlassian-webhooks-api. Luckily in your case, this is sufficient for what you are trying to do.

Hello Andrew,

Thanks for your quick response and it works! Thanks again!

Yaoqi Huang

1 Like

Hello @aswan,

Thanks again for your previous solution.
But after I continue to develop with this, I found that if I use the WebHookListenerStore to addWebhook, the newly created webhooks won’t be retrieved until I restart the Jira or manually create webhook on web page/via RESTful API. I think there is a cache layer when I retrieve webhooks on web page/via RESTful API. And the cache layer is provided by the package com.atlassian.jira.plugins.webhooks.jira-webhooks-plugin.
I’ve searched and came up with some ideas to solve but none of them works.

  • I’ve tried to add this jira-webhooks-plugin package in the pom Import-Package module but the plugin still failed to start.
  • I found that there is a class called WebHookClearListenerCacheEvent in the com.atlassian.webhooks.atlassian-webhooks-api package. In the java doc, there is no method provided in this class, the description only says that Raise if you want webhook listener cache cleared.. But the class cannot be raised.

Could you kindly help me on this issue? Do the above solutions work? Or is there another way that I’ve missed?

Yaoqi Huang

Do you actually want to create webhook listeners, or do you just want to create webhooks? Because if it’s the latter, you should inject the com.atlassian.webhooks.WebhookService and call create(WebhookCreateRequest) on it.