Nav

About Class Loading Isolation

The Mule Runtime engine is developed using Java and many other third party libraries. Mule apps can also contain other Java libraries, particularly extensions that provide integration functionality, such as the HTTP connector. These extensions can also contain other JAR libraries.

The Problem

The default class loading mechanism of the JVM makes it possible to have conflicting versions of the same JAR files. In Mule, each artifact (the runtime, the Mule apps, and Mule extensions) is developed and released independently, but the JARs for these artifacts are together in the same location. For example, a Mule app might use Apache Commons Collections 2.1. If an extension you use requires Apache Commons Collections 3.1, the app might not work as expected because Commons Collections 2.1 and Commons Collections 3.1 have conflicting resources.

Mule 3 Solution

To solve the problem of clashes between different apps, Mule 3 relied on hierarchical organization of class loaders. Though Mule apps can see their extensions, the libraries bundled within them, and their runtime libraries, Mule apps cannot access other app libraries.

Other potential conflicts remained in Mule 3, such as clashes between libraries from different extensions, clashes between extension and app libraries, and clashes between app and runtime libraries.

Mule 4 Solution

In Mule 4, the class loading mechanism addresses all the problems depicted above for Mule 3.

API Definition

The Mule runtime and artifacts (apps, domains, policies, and extensions) need to have a clear API definition that specifies a contract for each artifact and limits the exposure of the artifact content to other artifacts.

A clear API for each artifact provides a way to limit the scope of classes and libraries, which in turn makes it possible to create class loaders that do not share everything.

Mule 4 API

Mule 3 exposes all the classes that are bundled within its libraries. This exposure caused problems when upgrading from one runtime to another because changes in the runtime could potentially affect any of your custom Java classes.

Mule 4 provides a well-defined API that makes it easier for you to extend Mule and provides clarity on the proper extension points:

  • Core API: Mule message.

  • Extensions API: Modules, message processors, transforms, and other elements to extend Mule Runtime 4.

  • Tooling API: All DataSense metadata and propagation is now part of Mule Runtime 4. This API is bundled with the Mule Agent.

Artifact API

When you create an artifact (app, domain, policy, or extension), you need to declare the public API of that module.

How To Define the Public API

Go to this page to learn how to export a resource from an artifact.

Considerations
  • Resources and classes that are not exported are not visible from other artifacts.

  • Expose the minimum required set of packages and resources from your artifact.

  • Do not export third-party libraries unless required.

  • Never expose common third-party libraries like Guava, Apache common-collections, and so on. Doing so will cause clashes with other artifacts.

  • Ideally, expose only classes from your artifact (or the JDK).

Semver

Mule 4 follows Semantic Versioning 2.0.0 for all the provided APIs.

API restrictions

All public APIs might have restrictions. These restrictions limit how you can use the API. See API annotations module for more details.

You need to take into account the API restrictions defined for the API you are consuming, as they ensure greater flexibility among API changes that can occur between different versions.

Class Loading Isolation Mechanism

Once APIs are clearly defined, you can prevent access to internal classes of the artifact and only make the public API accessible from outside. To protect the APIs, Mule 4 uses a custom class loading mechanism.

Suppose you have the following extension file structure:

com/example/extension/api/MyClass.class
com/example/extension/internal/Util.class
transformations/customer-to-user.dwl
license.txt
META-INF/mule-artifact/mule-artifact.json

And the following mule-artifact.json descriptor file for the extension:


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
    "name": "my-test-extension",
    "minMuleVersion": "4.0.0",
    "classLoaderModelLoaderDescriptor": {
        "id": "mule",
        "attributes": {
            "exportedResources": [
                "transformations/customer-to-user.dwl"
            ],
            "exportedPackages": [
                "com/example/extension/api"
            ]
        }
    }
}

Though somewhat oversimplified, this diagram shows how resources exported by mule-artifact.json are applied within an app:

Simple classloading diagram

Artifact Class Loader

A regular Java class loader pointing to the JAR files included in the extension. This class loader will load all files and classes of the extension.

Artifact Filtering Class Loader

A wrapper created over the Artifact class loader, which will enforce the access restrictions to the extension code for foreign artifacts (the app or other plugins). It uses the content of the mule-artifact.json descriptor to determine what is public.

Extension code

The Mule extension code. It uses Artifact class loader (which does not have any restriction), and it is only able to locate resources of the plugin itself.

Application Code

The Mule app code. It uses the Artifact Filtering class loader of the extension to prevent the app from accessing restricted code or resources.