Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Converting User Macro (Confluence Data Center) to custom Forge app (Confluence Cloud)

Matt
Contributor
January 13, 2026

I have two User Macros in Confluence Data Center:

  • noprint - excludes content within this block from being rendered with a page is exported to PDF.
  • pagebreak - create a pagebreak when a page is exported to PDF.

We are migrating to Confluence Cloud, and I have created a custom Forge app to provide this same functionality. I would now like to try to have the Confluence Cloud Migration Assistant (CCMA) handle the migration of these User Macros to the new Forge app. Based on the documentation, it seems possible, but I have not been able to get it to work. Here are some things I have setup to try to get this working:

  1. Create a P2 app to replace the User Macros in Data Center (this is working).
  2. The P2 app and Forge app both use the same name for the macros:
    1. P2 app's "atlasian-plugin.xml"
      1. key="noprint" name="noprint"
      2. key="pagebreak" name="pagebreak"
    2. Forge app's "manifest.yml"
      1. key: noprint
      2. key: pagebreak
  3. The P2 app has a migration listener class that implements "DiscoverableForgeListener" and "ConfluenceAppCloudMigrationListenerV1"
    1. getForgeAppId() returns the app.id from the Forge app's "manifest.yml"
    2. getForgeEnvironmentName() returns "ForgeEnvironmentName.STAGING", this is for testing, and is planned to be switched to PRODUCTION when we migrate production.
    3. getCloudAppKey() returns "null", as it is a custom (non-Marketplace) app.
    4. getServerAppKey() returns the <groupId>.<artifactId> of the app.
    5. getDataAccessScopes() returns 
      EnumSet.of(
      MIGRATION_TRACING_PRODUCT,
      MIGRATION_TRACING_IDENTITY,
      PRODUCT_DATA_OTHER,
      APP_DATA_OTHER
      )
    6. getServerToForgeMacroMapping() returns the mapping of macro names (same between P2 and Forge)
      Map<String, String> macroMappings = new HashMap<>();
      macroMappings.put("noprint", "noprint");
      macroMappings.put("pagebreak", "pagebreak");
      return macroMappings;
  4. The "plugin-context.xml" contains "<atlassian-scanner:scan-indexes/>" so that I can set "@Component" on the listener.
  5. I've followed steps documented on these pages:
    1. https://developer.atlassian.com/platform/app-migration/tutorials/p2-to-forge-macros/
    2. https://developer.atlassian.com/server/framework/atlassian-sdk/configuration-of-instructions-in-atlassian-plugins/
    3. https://bitbucket.org/atlassian/atlassian-spring-scanner/src/master/
  6. When setting up the migration between Confluence Data Center and Confluence Cloud, the app is not set to migrate, since I can't provide an app to migrate to in Cloud (since my custom Forge app is not in Marketplace). Atlassian documentation indicates that it should pickup my listener with what I've documented above.

In my listener code I have "log.info" and "System.out.println" statements to try to see if there is any output in my log files on Confluence Data Center, but nothing is printed.

After migration, any use of the P2 macros just appear in Confluence Cloud as "Error loading the extension!".

Any ideas on how to get this migration to help would be greatly appreciated. Thanks.

1 answer

0 votes
marc -Collabello--Phase Locked-
Community Champion
January 13, 2026

A related question: Do the Forge apps actually work when printing? I.e. is the noprint content not in the PDF?

Matt
Contributor
January 14, 2026

The Forge app does work. Any content in the body of the "noprint" macro is excluded from an exported PDF.

marc -Collabello--Phase Locked-
Community Champion
January 14, 2026

Thanks!  I was thinking this would stop working after Connect, however it also seems possible in Forge.

Can I ask how you made the "noprint" macro?

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
PREMIUM
PERMISSIONS LEVEL
Product Admin
TAGS
AUG Leaders

Atlassian Community Events