Loading
システム管理者に対するフィッシング耐性MFA・全従業員ユーザーMFAの適用のお知らせ 続きを読む

NoClassDefFoundError for Third-Party Libraries After Upgrading to Mule Runtime 4.11.x

公開日: Jul 14, 2026
説明

Overview

After upgrading from Mule Runtime 4.9.x to 4.11.x, applications using custom mule-plugin modules may encounter a java.lang.NoClassDefFoundError at runtime for third-party library classes (e.g. com.fasterxml.jackson.core.JsonFactory), even though the application compiled and deployed successfully. No code or POM changes are required to trigger this issue — simply changing the runtime version is sufficient.

java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory
at com.example.customplugin.utils.JsonUtils.processJson(JsonUtils.java:694)
at com.example.customplugin.utils.JsonUtils.sortData(JsonUtils.java:1086)
  • Application compiles successfully on both runtimes
  • Application deploys successfully on both runtimes
  • Error occurs only at runtime when the method using the third-party library is invoked
  • No code or POM changes were made — only the Mule runtime version was changed

Scenario That Triggers This Issue

The following conditions together cause the error:

  1. Plugin A (custom mule-plugin) uses a third-party class (e.g. JsonFactory from jackson-core) internally — but does NOT declare that library as its own dependency in its pom.xml
  2. Plugin B (another mule-plugin in the same app, e.g. a logging plugin) bundles the same third-party library — but does NOT export its packages in mule-artifact.json
  3. On 4.9.x this worked because Plugin B's transitive libraries leaked into Plugin A's classloader implicitly at build time

On 4.11.x this fails because strict classloader isolation prevents Plugin A from accessing any class it does not own.

Note: This issue commonly surfaces after connector/plugin version bumps driven purely by minMuleVersion compatibility requirements for 4.11.x — even when no code or dependency logic was changed.

Root Cause

This is caused by a classloader isolation behaviour change between Mule 4.9.x and 4.11.x:
On Mule 4.9.x (Working):

  • The classloader-model generation tooling (mule-extensions-maven-plugin v1.9.x / mule_maven_client v2.4.x) was permissive: when Plugin A declared a dependency on Plugin B, Plugin B's transitive Java JARs (e.g., jackson-core) were promoted into Plugin A's classloader-model.
  • At runtime, Jackson classes were physically present within Plugin A's own classloader scope.
  • ChildOnlyLookupStrategy resolved them successfully from the local classloader; the RegionClassLoader was never consulted.
  • This implicit transitive promotion was unintentional and undocumented.

On Mule 4.11.x (Failing):

  • The classloader-model generation tooling (mule-extensions-maven-plugin v1.11.x / mule_maven_client v2.6.x) now enforces strict isolation: a dependency on another mule-plugin no longer flattens the inner plugin's transitive Java JARs into the outer plugin's classloader-model.
  • At runtime, Jackson classes are no longer present in Plugin A's classloader scope.
  • ChildFirstLookupStrategy attempts to resolve locally first (and fails), then escalates to the RegionClassLoader.
  • The RegionClassLoader enforces strict package-mapping. Because the Jackson packages are neither registered as sharedLibraries nor exported by any plugin, the class is rejected with a "no package mapping for region" error.
  • Result: NoClassDefFoundError

Key Distinction: The root cause is the change in the build-time classloader-model packaging behavior (which JARs are placed into each plugin's classpath), NOT a change in the runtime lookup strategy semantics. Both ChildOnlyLookupStrategy and ChildFirstLookupStrategy have existed since Mule 4.0. What actually changed is which JARs are physically available to each strategy at runtime.

In one sentence:

On 4.9.x, the build-time classloader-model generator promoted transitive Java JARs from sibling mule-plugins into the depending plugin's classpath scope, allowing ChildOnlyLookupStrategy to resolve them locally. On 4.11.x, this transitive promotion was removed to enforce stricter plugin isolation (mule-extensions-maven-plugin v1.11.x / mule_maven_client v2.6.x), meaning libraries not explicitly declared in a plugin's own pom.xml are no longer present in its classloader scope at runtime, which results in a NoClassDefFoundError when those classes are first referenced. The application code remained unchanged; only the runtime and its build tooling changed.

Evidence — Verbose Classloading Logs

Mule 4.9.x (Working — Illustrative Example):

DEBUG Loading class 'com.fasterxml.jackson.core.JsonFactory'
   with 'ChildOnlyLookupStrategy'
   on MulePluginClassLoader[app/my-application/plugin/custom-plugin]@<hash>

DEBUG Loaded class 'com.fasterxml.jackson.core.JsonFactory'
   from child: MulePluginClassLoader[app/my-application/plugin/custom-plugin]@<hash>
→ Class resolved successfully from the plugin's own classloader (Jackson JARs were promoted into this plugin's scope via transitive packaging).
→ Application works.

Mule 4.11.x (Failing — Illustrative Example):

DEBUG Loading class 'com.fasterxml.jackson.core.JsonFactory'
   with 'ChildFirstLookupStrategy'
   on MulePluginClassLoader[...plugin/custom-plugin]

DEBUG Loading class 'com.fasterxml.jackson.core.JsonFactory'
   with 'ChildFirstLookupStrategy'
   on RegionClassLoader[container/app/my-app]

WARN  Cannot load class 'com.fasterxml.jackson.core.JsonFactory':
   Class has no package mapping for region 'container/app/my-app'
   Class not found in classloader for artifact 'container'

ERROR java.lang.NoClassDefFoundError:
   com/fasterxml/jackson/core/JsonFactory ❌

Note : The lookup strategy shown (ChildOnlyLookupStrategy vs. ChildFirstLookupStrategy) depends on whether the class is physically present within the plugin's resolved classloader-model scope — not directly on the Mule Runtime version. What actually changes between 4.9.x and 4.11.x is whether the class is found in the local scope at all, due to the build-time packaging model change.



How to Enable Verbose Classloading for Diagnosis

To capture the classloader chain and confirm which plugin is loading (or failing to load) a class:
VM Arguments:

-Dmule.classloading.verbose=true
-Dmule.verbose.exceptions=true

log4j2.xml:

<AsyncLogger name="org.mule.runtime.module.artifact.api.classloader" level="DEBUG"/>
<AsyncLogger name="org.mule.runtime.module.artifact.api.classloader.exception.NotExportedClassException" level="TRACE"/>

In Anypoint Studio, add VM arguments under:

Run → Run Configurations → Arguments tab → VM Arguments
解決策

Fix

Option 1 — Recommended: Explicitly declare the dependency in the custom plugin (permanent fix)

Add the missing library as an explicit dependency in the custom plugin's own pom.xml:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${jackson.version}</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>

NOTE:
"Do not hardcode a specific Jackson version. Instead, align your Jackson version with whatever is already bundled by your other plugins (check their POMs) or with your Mule runtime distribution. Using a static version that conflicts with an already-loaded Jackson instance in the same region can trigger runtime conflicts."

Option 2: Declare as sharedLibraries in the application POM

If modifying the plugin source is not immediately possible, declare the library as a sharedLibrary in the application's mule-maven-plugin configuration:

<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>${mule.maven.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<sharedLibraries>
<sharedLibrary>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</sharedLibrary>
<sharedLibrary>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</sharedLibrary>
</sharedLibraries>
</configuration>
</plugin>

This promotes the library to the RegionClassLoader level, making it visible to all plugins in the application.

Option 3: Export the packages from the plugin that owns them —Last Resort Only

If you own the plugin that bundles the library (e.g., mule-json-logger), you must add the third-party packages to its mule-artifact.json under theclassLoaderModelLoaderDescriptor.attributes.exportedPackages array.

Note: exportedPackages is NOT a top-level field. It must be nested under the correct path, otherwise the runtime will silently ignore it.

Important:
You must retain the plugin's own packages (e.g., org.mule.extension.jsonlogger) within the exportedPackages list. Do not replace them entirely with the third-party packages.

{
"classLoaderModelLoaderDescriptor": {
"id": "mule",
"attributes": {
"exportedPackages": [
"org.mule.extension.jsonlogger",
"com.fasterxml.jackson.core",
"com.fasterxml.jackson.core.type",
"com.fasterxml.jackson.core.util",
"com.fasterxml.jackson.databind",
"com.fasterxml.jackson.databind.node"
]
}
}
}

Use this option only as a last resort. This approach has significant risks:

  • Breaks encapsulation: Exposing internal third-party packages violates the classloader isolation model Mule 4.11.x deliberately enforces.
  • Version conflict risk: Multiple plugins loading different versions of the exported library may cause LinkageError or ClassCastException at runtime.
  • Dependency on third-party ownership: Requires modifying the plugin that bundles the library. If you don't own it, this option isn't available.

    Always prefer Option 1 as the primary fix. Only consider Option 3 if you own the exporting plugin and cannot modify the consuming plugin.

OPTIONS SUMMARY: 
  • Option 1 (Recommended): Explicitly declare the dependency in the plugin's pom.xml. Cleanest fix.
  • Option 2 (Temporary workaround): Declare as sharedLibrary at the application level.
  • Option 3 (Last resort): Export packages from the owning plugin — only if you own it and can't use Options 1 or 2.

Common Trigger — Upgrading Plugin Versions for minMuleVersion Compatibility

This issue commonly surfaces during Mule 4.9.x → 4.11.x upgrades when teams rebuild custom plugins solely to satisfy the minMuleVersion requirement — with zero code or dependency changes.

Migration Warning: If upgrading from 4.9.x to 4.11.x and your custom plugins required version bumps purely for minMuleVersion compatibility, audit each plugin's pom.xml to ensure all third-party libraries are explicitly declared — do not rely on transitive visibility from sibling plugins.

Key Principle for Mule 4.11.x and Later

Each mule-plugin must explicitly declare ALL third-party libraries it depends on in its own pom.xml. Relying on implicit class visibility from sibling plugins is no longer supported in Mule 4.11.x due to stricter classloader isolation enforcement.

This behaviour change was introduced in Mule 4.11.x as part of stricter plugin classloader isolation. Applications that were working on 4.9.x by relying on implicit transitive class visibility from sibling plugins will need to explicitly declare those dependencies when upgrading to 4.11.x.

ナレッジ記事番号

005388792

 
読み込み中
Salesforce Help | Article