RFC-132: Removal of Third-Party Libraries from Data Center Public API

RFCs are a way for Atlassian to share what we’re working on with our valued developer community.

It’s a document for building shared understanding of a topic. It expresses a technical solution, but can also communicate how it should be built or even document standards. The most important aspect of an RFC is that a written specification facilitates feedback and drives consensus. It is not a tool for approving or committing to ideas, but more so a collaborative practice to shape an idea and to find serious flaws early.

Please respect our community guidelines: keep it welcoming and safe by commenting on the idea not the people (especially the author); keep it tidy by keeping on topic; empower the community by keeping comments constructive. Thanks!

Project Summary

As part of the upcoming major release of Atlassian Data Center products, we are reviewing which third-party libraries are exported through the Data Center public API. We are proposing to stop exporting a number of third-party libraries, which means they would no longer be provided by the host product to plugins at runtime. Affected apps would need to bundle these libraries themselves.

This RFC covers all Data Center products: Jira Software/JSM 12, Confluence 11, Bitbucket 11, Bamboo 13 and Crowd 8.

  • Publish: 2026-04-21T22:00:00Z
  • Discuss: 2026-05-12T22:00:00Z
  • Resolve: 2026-05-26T22:00:00Z

Problem

What is the problem?

Atlassian Data Center products currently export many third-party libraries through their public API. This means that apps (plugins) can import these library packages at runtime from the host product via OSGi, without bundling them.

While this was convenient when it was introduced, it creates several long-term challenges:

  • Security response time: When a library is part of the public API, upgrading it is a backward-incompatible change. Even critical CVE patches require coordination with the entire app ecosystem, slowing response from days to weeks.
  • Version lock-in: Apps are tied to whatever version of a library the DC products ship. They cannot use newer versions with bug fixes or features, nor can they stay on an older version that they have tested against.
  • Upgrade friction: Every major release upgrade that bumps a public API library version risks breaking apps that depend on specific behaviors of the old version.
  • Stable support commitment: The upcoming major release of Data Center products is designed for long-term stability. Each library exposed on the public API is a commitment to maintain it without frequent disruptive changes.

Who has the problem?

  • Atlassian: maintaining version compatibility across a large set of exported libraries constrains our ability to respond to security issues and evolve our Data Center products.
  • App vendors: locked to the DC product’s library version, unable to independently manage their own dependency lifecycle.
  • Customers: delayed security patches and slower product evolution.

Why does it need to be solved now?

This upcoming major version release is a natural boundary point to make backward-incompatible changes. Once these DC products ship, the public API surface will be locked for the extended support lifecycle. Reducing the API surface now avoids locking in commitments that will constrain security responses for years to come.

What benefit is there to solving the problem?

  • Atlassian can patch library CVEs independently of app ecosystem coordination.
  • App vendors gain freedom to pin the exact library version they need.
  • Reduced public API surface means fewer surprise breakages during future upgrades.
  • Smaller API commitment during the extended support phase.

Proposed Solution

Overview

We propose to remove a number of third-party libraries from the Data Center public API. Concretely, this means:

  • Data Center products will stop exporting these library packages to apps via OSGi.
  • The libraries may still remain on the product’s internal classpath for Atlassian’s own use, but apps will no longer be able to rely on them being available at runtime.
  • Apps that depend on these libraries will need to bundle them directly — include the JAR in the app’s build.

Libraries proposed for removal

The following libraries are proposed for removal from the Data Center public API. For each library we list the primary Java package prefix and the products that currently export it. If your app targets a product not listed for a given library, your app is not affected by that specific change.

Exported by all (or most) products:

  • Bouncy Castle (org.bouncycastle) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • Commons Codec (org.apache.commons.codec) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • Commons Collections 3 (org.apache.commons.collections) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • Commons IO (org.apache.commons.io) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • Commons Lang 3 (org.apache.commons.lang3) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • Commons Text (org.apache.commons.text) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • org.json (org.json) — Jira, Confluence, Bitbucket, Crowd, Bamboo
  • net.oauth (net.oauth) — Jira, Confluence, Crowd, Bamboo
  • JSoup (org.jsoup) — Jira, Confluence, Crowd, Bamboo
  • Xerces (org.apache.xerces) — Jira, Confluence, Crowd, Bamboo

Exported by a subset of products:

  • Checker Qual (org.checkerframework) — Confluence, Crowd, Bamboo
  • Xalan (org.apache.xalan, org.apache.xml.serializer) — Confluence, Crowd, Bamboo
  • XStream (com.thoughtworks.xstream) — Confluence, Bamboo
  • Stax2 API (org.codehaus.stax2) — Confluence, Bamboo
  • JDOM 2 (org.jdom2) — Jira, Bamboo
  • Joda-Time (org.joda.time) — Jira, Bamboo
  • ROME (com.rometools) — Jira, Bamboo
  • log4j-core (org.apache.logging.log4j.core) — Jira, Bamboo
  • ORO (org.apache.oro) — Jira, Bamboo
  • OpenSymphony OSCore (com.opensymphony.util) — Jira, Confluence
  • JTidy (org.w3c.tidy) — Jira, Confluence
  • Reactive Streams (org.reactivestreams) — Crowd, Bamboo
  • Gson (com.google.gson) — Bamboo
  • Commons Lang 2 (org.apache.commons.lang) — Bamboo
  • Commons BeanUtils (org.apache.commons.beanutils) — Bamboo
  • Commons Collections 4 (org.apache.commons.collections4) — Bamboo
  • Commons Compress (org.apache.commons.compress) — Bamboo
  • Commons Configuration (org.apache.commons.configuration) — Bamboo
  • Commons CLI (org.apache.commons.cli) — Bamboo
  • Commons Daemon (org.apache.commons.daemon) — Bamboo
  • Commons Digester (org.apache.commons.digester) — Bamboo
  • Commons JXPath (org.apache.commons.jxpath) — Bamboo
  • Commons Validator (org.apache.commons.validator) — Bamboo
  • Commons FileUpload 2 (org.apache.commons.fileupload2) — Jira
  • Commons Pool 2 (org.apache.commons.pool2) — Jira
  • JFreeChart (org.jfree) — Jira, Bamboo
  • ROME 1.0 (com.sun.syndication) — Jira
  • ICU4J (com.ibm.icu) — Confluence
  • Logback (ch.qos.logback) — Bitbucket

Note on log4j: Only log4j-core (the implementation) is proposed for removal. log4j-api (the logging facade) will remain on the public API. Standard logging via LogManager.getLogger() is unaffected.

Developer experience: How to check if your app is affected

Your app is affected if it imports packages from any of the proposed-for-removal libraries and relies on the host product to provide them (i.e., does not already bundle the library).

Step 1: Check your app’s OSGi Import-Package header

The most reliable way to determine what your app imports from the host product is to inspect the Import-Package header in your app’s built JAR file:

unzip -p your-plugin.jar META-INF/MANIFEST.MF | awk '/^Import-Package:/{found=1} found{if(/^[^ ]/ && !/^Import-Package:/){exit} print}'

Look for any of the package prefixes listed above. If present, your app currently relies on the host product to provide that library.

Step 2: Cross-reference with your source code

Search your Java source files for import statements matching the package prefixes:

grep -rE "import (org\.apache\.commons\.codec|org\.apache\.commons\.collections[^4]|org\.apache\.commons\.io|org\.apache\.commons\.lang3|org\.jsoup|org\.json)" src/

Step 3: Check your build configuration

If your build declares a library with provided scope (Maven) or compileOnly (Gradle), your app depends on the host product to provide it at runtime. If the dependency uses compile scope (default) and is included in your final JAR, you already bundle it and are not affected.

Step 4: Check for transitive dependencies

Some libraries may be pulled in transitively. Check your full dependency tree:

mvn dependency:tree | grep -E "commons-codec|commons-collections|commons-io|jsoup|org.json"

Ecosystem impact: What you need to do if affected

Option A: Bundle the library (recommended, quickest fix)

Change the dependency from provided to compile scope so it gets included in your app’s JAR:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.17.1</version>
    <scope>compile</scope>  <!-- or without `scope` - `compile` is the default one -->
</dependency>

Most of the shortlisted libraries set for removal are compact, self-contained JAR files with either no or very few transitive dependencies, which simplifies the bundling process. We recognize that these changes could increase the overall application size, and we will factor this consideration into the final decision.

Option B: Migrate to JDK or alternative APIs

Some libraries have direct JDK equivalents:

  • Commons Codec (Base64, Hex) → java.util.Base64, HexFormat (Java 17+)
  • Commons IO → java.nio.file.Files, InputStream.transferTo()
  • Commons Collections 3 → java.util.stream, Collections API
  • Commons Lang 3 (partial) → Objects, String.isBlank() (Java 11+), though no full drop-in replacement exists for the complete StringUtils API

Asks

We are sharing this RFC to gather input from the app developer community before we finalise our decisions. Your feedback matters and will be taken seriously - it is one of several factors we will weigh when deciding which libraries to remove, which to retain, and on what timeline.

Please note that this is not a vote. Feedback from external vendors is an important data point, but our final decisions will be based on a broader multi-factor analysis - including security posture, maintenance burden, ecosystem impact, and product strategy - running in parallel to this feedback period and potentially extending beyond it. We may proceed with removing a library even if we receive objections, if other factors outweigh the concerns raised. Equally, we may decide to retain certain libraries even in the absence of specific feedback, if our deeper analysis points in that direction.

With that context in mind, while we would appreciate any reactions you have to this RFC (even if it’s simply giving it a supportive “Agree, no serious flaws”), we’re especially interested in learning more about:

  1. Which specific libraries from the proposed removal list would significantly impact your app(s) if removed? Please be specific about which library, which product(s), and how widely it’s used in your codebase.

  2. Are there cases where bundling would be particularly difficult? For example, libraries that must share a single instance with the host product (e.g., shared caches, singletons), or where classloader isolation causes issues.

  3. Are there libraries not on this list that you think should also be considered for removal? Or libraries on the “remove” list that you believe should stay, and why?

  4. Are there other impacts we haven’t anticipated? For example, interactions between multiple libraries, app-to-app dependencies, or edge cases with specific product versions.

3 Likes

Hi @MarekTokarski

Thanks for putting this detailed guide together.

My main question about all of this is: why?

With DC EOL front and centre, and vendors being actively encouraged by Atlassian to avoid adding any substantial features to their DC offerings, this effort has the potential to create a bunch of additional work for vendors for products that now have an uncertain future, and thus limited return. Many vendors are looking to minimize the time spent on maintaining their EOL products.

This procedure made a fair amount of sense for platform 7 (and to a lesser extent with platform 8). I would have guessed by now that Atlassian has already previously removed substantially all third-party library signatures from public APIs. Is this not actually the case?

You mentioned some of the following goals for making this change:

  • Security response time: When a library is part of the public API, upgrading it is a backward-incompatible change. Even critical CVE patches require coordination with the entire app ecosystem, slowing response from days to weeks.

The mass removal of library exports creates a breakage of all dependent software as part of the major release, as opposed to a theoretical mid-release breakage if a future upgrade should ever need to happen.

Could Atlassian consider perhaps just changing the API contract so that these third-party components (meaning non-com.atlassian.*) do not have any explicit guarantees to remain on a stable version within the platform version release?

If it breaks mid-major, vendors will simply have to deal with it. This already happens with some frequency with first-party Atlassian packages, so I do not see third party breakage as being significantly different.

  • Version lock-in: Apps are tied to whatever version of a library the DC products ship. They cannot use newer versions with bug fixes or features, nor can they stay on an older version that they have tested against.

I believe apps can still choose to bundle their own version if they want to override the host product export?

  • Upgrade friction: Every major release upgrade that bumps a public API library version risks breaking apps that depend on specific behaviors of the old version.
  • Stable support commitment: The upcoming major release of Data Center products is designed for long-term stability. Each library exposed on the public API is a commitment to maintain it without frequent disruptive changes.

I think both of these could potentially fall under the “caveat emptor” principle for the vendors who choose to use such libraries? Maybe adjust the Maven banned dependencies plugin to print out big warnings for any imports of these features, but to allow them to remain?

In summary, vendors would appreciate any efforts on Atlassian’s part to reduce the amount of effort needed to maintain dying products, and I hope that the above might represent a way to do this that is compatible with Atlassian’s security posture.

18 Likes

As we said when it was announced that a new Confluence 11 major version was coming:

If 11.x requires us to add a third build, we’ll have to seriously consider whether it’s worth continuing to offer DC versions given the dwindling expected sales.

The same sentiment applies here.

If this materially increases the amount of effort we must spend supporting future versions of DC products, then we will simply sunset our DC app offerings at the last supported version prior to the breakage.

This would purely be a business decision, as it makes little sense to continue to invest in a product that is ~2.8 years away from EoL, where the existing customer base is actively planning migrations away from the platform (either to Cloud, or away from Atlassian entirely).

I would urge you to consider whether this juice is truly worth the squeeze.

4 Likes

Hi @MarekTokarski ,

Thank you for the additional context in the RFC. I fully agree with @scott.dudley and @scottohara . I’ve reviewed the ‘Problem’ and ‘Why now?’ sections, and I still find the ‘long-term challenges’ argument logically inconsistent with the current product lifecycle.

1. The Timeline Paradox

The RFC mentions that this release is designed for ‘long-term stability.’ However, in the context of the End of Life (EoL) within 3 years, the ‘long-term’ is effectively already over. These convenience exports were introduced by Scott and Mike over 20 years ago; they have been the status quo for decades.

If Atlassian and the ecosystem have managed these ‘challenges’ for 20 years, why is it necessary to break them now, for products that will only exist for another ~1,000 days?

2. Security vs. Stability

The RFC cites Security response time as a driver. While true in a vacuum, the reality is that moving the burden of bundling and patching to the App Vendors during a product’s sunset phase creates a different kind of risk:

  • Fragmentation: Instead of Atlassian patching a library once in the core, hundreds of vendors must now release individual updates for their own bundled versions.

  • Overhead: For apps that are also in ‘maintenance mode’ due to the EoL, this is a significant tax for very little remaining ROI.

3. Why wasn’t this a 2.x/3.x Priority?

The most logical time for this ‘de-coupling’ was decades ago. Doing it now feels like an architectural cleanup that serves Atlassian’s internal maintenance convenience rather than providing actual value to the vendors.

My main question remains: Since the public API surface will be locked for the ‘extended support lifecycle’ (which is quite short), why not prioritize stability and continuity for the remaining 3 years, rather than forcing a major architectural shift on a community that is already navigating the transition away from Data Center?

5 Likes

Hi @scott.dudley, @scottohara, @istvanverhas,
Thank you all for engaging with this RFC — these are important questions and they deserve a thorough response. The common thread across your comments is: “DC has ~3 years left, why create work now?” We understand this concern, and we want to be transparent about our reasoning.

On the timeline

DC has an extension program beyond the announced EOL, and we are designing for that extended horizon. Major versions exist precisely to contain breaking changes in a controlled, predictable way - this is the right moment to address this, and doing it later would be worse for everyone.

On security

The rate at which vulnerabilities are discovered in existing software has increased significantly in recent years. Libraries that have been stable for years - or even decades - are not immune: they simply haven’t been looked at closely enough yet.

When a critical CVE hits a library that is part of our public API contract, we face a coordination problem: even if a fix is available, shipping it means a breaking API change - planning, communicating, waiting for the ecosystem. That delay is measured in weeks, precisely when rapid response matters most. And for libraries with no active upstream maintainer, even the fix may not come at all.

We want to be in a position to act quickly when the next critical vulnerability arrives, not be blocked by a contract we wrote years earlier. Over an extended maintenance horizon, that’s not a theoretical risk.

On “just relax the contract” (Hyrum’s Law)

Several of you have suggested we simply remove the stability guarantee rather than removing the exports entirely. We’ve thought about this carefully, and Hyrum’s Law is the core reason we don’t think it works: with a sufficient number of users of an API, all observable behaviours will be depended upon by somebody, regardless of what the contract says.

If we break these exports mid-major late in the product’s lifecycle - even under a “best effort” label - the reaction will be significantly worse than a clean break at a major version boundary today. At that point, migration guides will be harder to produce, timing will be unpredictable, and apps may have far less active development resource behind them. We are choosing the harder path now precisely because it is the more respectful path to vendors in the long run.

On fragmentation — this is already happening

@istvanverhas raises the point that removing these libraries shifts the patching burden from Atlassian (patch once) to hundreds of individual vendors. This is a fair concern in principle, but for the majority of libraries on this list, vendors are already bundling their own copies rather than relying on our export.

To give two concrete examples: roughly two thirds of apps importing JSoup or org.json already bundle their own copy. For those apps, the fragmentation already exists alongside our platform copy. Removing our export doesn’t introduce fragmentation — it eliminates one redundant instance of it, and removes the contractual constraint that prevents us from acting when we need to.

On effort

Our goal is to make this as easy as possible. For most libraries, the minimal change is simply to start bundling the dependency directly - a build configuration change, not a code change. For those willing to go further, most of the proposed libraries are good candidates for full removal from your app, replaceable with standard alternatives.

However, the list is long, and not every library on it will be relevant to every app. Before drawing conclusions about the overall impact, we’d encourage you to review the list against your actual dependencies. You may find that several entries don’t affect your apps at all.

More importantly: if you identify a specific library that represents a genuine migration challenge - something that isn’t simply a matter of bundling, or where the migration path is unclear - please tell us. That is precisely what this RFC process is for, and that kind of specific, concrete feedback directly shapes our priorities and the support we provide. We have already acted on early feedback of this kind and are continuing to do so.

We genuinely appreciate the engagement. This is a difficult set of trade-offs and we don’t take the impact on vendors lightly.

Are Marketplace apps part of this extension program (and does that mean we can expect further revenue, and provide support, beyond the EoL date?)

All the reasons above are perfectly valid, but again as a business we need to consider the cost of continuing to invest in the platform against a decreasing revenue stream.

Again I’ll point to the Confluence 9 → 10 transition that forced incompatible pom.xml changes, resulting in us now maintaining and building two versions for every release, one for 8.x-9.x, and one for 10.x.

If what you’re saying is that these build configuration changes are fully backwards compatible with our current 10.x pom.xml file then yes, that’s a simple one-time change.

If not, and we have to maintain a third pom.xml configuration for 11.x, then we simply won’t.

We’ll happily forgo any further DC revenue between now and March 2029 and focus all of our engineering resources entirely on our Forge versions.

Hi @MarekTokarski

I appreciate the candour in your response. While I have a different opinion about what constitutes the better path for vendors in the long run, Atlassian’s concerns are valid and it is obviously up to your team to make the best choice.

I would then reframe my request as follows: so long as you are going to remove packages from exports in this upcoming platform release, can Atlassian please do it all now and get rid of absolutely everything third-party that you might ever vaguely even consider removing in the future? (Or maybe you have done this already?)

Vendors had to contend with a bunch of exports being removed in platforms V.x-2, V.x-1, and now V.x. When the zombie of DC past comes back in two years and Atlassian is looking at platform V.x+1 for the super-duper extended EOL for extra-fancy customers, vendors do not want to have to deal with yet another set of removals. If we have to do it, I would rather do this now and get it all over with instead of continuing to do it piecemeal, for some of the very same reasons you mentioned (apps currently having more active development and resources behind them).