Classloader Control in Mule
This topic introduces you to classloading in Mule and shows you how to override classloading in your applications and plugins.
Mule uses classloaders to find and load classes for execution. When Mule uses classloaders, it does so in the following order:
The bootstrap, extensions, and CLASSPATH class loaders created by the Java virtual machine. This classloader loads the core Java libraries.
The Mule System class loader. This classloader loads standard Mule libraries, that is, libraries in the
<MULE_HOME/lib>directory and subdirectories, where
<MULE_HOME>is the directory where Mule ESB is installed.
One or more shared domain classloaders. These classloaders are used to share libraries between applications or allow an application to use a different version of a library. These libraries are in the
<domain>is the domain of the application. The shared domain classloader is optional, there is none by default.
One or more Mule application class loaders that load classes or libraries from a Mule application, that is, libraries in the
<myapp>is the name of the application.
The Mule classloader order is illustrated in the following diagram:
Although this classloading architecture meets most classloading needs, there are times when you might need to override the default classloading scheme. For example, suppose an application requires a third-party library that is bundled with it. This might conflict with a libary version that the shared domain classloader would load (that is, a version of the library already bundled with Mule). How do you ensure that the required version of the library is used with the application? To address requirements such as these, Mule 3.2.0 added support for fine-grained class loading control that enables you to override defaul classloading.
Mule introduces a new configuration property,
loader.overridge, that enables you to override default classloading. You specify the property in the
mule-deploy.properties file for the application, and identify a list of classes, packages, or both that will be used in overrides.
Each class or package in the list is specified with its fully-qualified name. For example, an override list that includes a class (
com.example.MyProvider) and a package (
com.sun.jersey) would be specified as follows:
1 loader.override=com.example.MyProvider, com.sun.jersey
| If a package is specified in the override list, it applies to all of its subpackages. For example,
You can also block the loading of a class so that the class lookup is done in the application and not in Mule. You specify blocking similarly to the way you specify class overrides, that is, using
loader.override. However, the fully qualified names of classes or packages in the list must be prefixed with a - (dash/minus sign). Here, is an example of blocking specification:
Blocking is a more advanced concept than class overriding, and many users will not need to consider it. But it is quite important for plugin developers. The difference between blocking and class overriding is that if a class is specified in the blocking list, its lookup is performed within the application or plugin only. In other words, if the class is provided by Mule, it will not be visible in the application or plugin. A
ClassNotFoundException is a valid outcome even if Mule does not have such a class on a system level.
Here is a diagram that illustrates how class loading is handled for class overrides and blocking. When you view the diagram note that every class loader has a parent class loader. Unless loader override is configured, a classloader first delegates the search for a class to its parent classloader before attempting to find the class itself (the classloader is the child of its parent classloader).
Mule now has a plugin system that allows applications to package the plugins they use, and optionally allow these plugins to control their class loading in the same way that applications do.
Enabling a plugin to control classloading can be quite useful. For example, a connector may bundle a third-party library that it’s been tested with (that is, a library different from one that Mule provides) and declare a preference to load a the third-party version. An application would just need to add a plugin that identifies the third-party library in a loader override. The loader override is specified as a property, loader.override in the plugin structure (in Plugin Layout below).
The module system also provides for a simple distribution format for Mule extensions with dependencies.
Mule plugins are deployed as part of Mule’s applications. The Mule application structure has been extended to add a
plugins top-level directory:
Here are some things to consider regarding the plugins:
Multiple plugins, such as connectors, can be bundled in the application.
The plugins are deployed in natural sort order by filename
Each plugin must be packaged as a zip file with a predefined structure (as shown in Plugin Layout below).
Exploded plugins are not currently supported. The rationale for this is to encourage and maintain a simple plugin distribution model of just one file.
The deployment lifecylce of the plugin is tied to the application.
The plugin layout is simplified version of a Mule app.
The following plugin properties are currently recognized:
loader.override - provides fine-grained control over class loading within a plugin. This is the same level of fine-grained class loader control that is available to an application (see Fine-Grained Class Loading Control). An application can indicate its classloading preference simply by including a plugin that specifies the loader.override property. The application does not need to do any extra classloader configuration. However, if necessary, the application can override any classloading preference the plugin declares.