Contact Us 1-800-596-4880

Forward Compatibility Patterns

When building forward-compatible modules, you often need to use newer SDK features while providing fallback behavior for older runtimes. The following patterns show how to implement conditional behavior based on the Mule runtime version.

Check the Mule Runtime Version

Use the @RuntimeVersion annotation to inject the current Mule Runtime version into your component. You can apply this annotation to fields of type org.mule.runtime.api.meta.MuleVersion.

The mule-sdk-api artifact has a dependency on mule-api for basic APIs that aren’t intended to evolve over time. MuleVersion is one of these stable APIs, so there’s no org.mule.sdk.api counterpart for it. You can safely use org.mule.runtime.api.meta.MuleVersion in forward compatible modules.
import org.mule.runtime.api.meta.MuleVersion;
import org.mule.sdk.api.annotation.RuntimeVersion;

public class MyOperations {

  @RuntimeVersion
  private MuleVersion runtimeVersion;

  public void myOperation() {
    if (runtimeVersion.atLeast("4.12.0")) {
      // Use newer feature
    } else {
      // Use fallback behavior
    }
  }
}

The MuleVersion class provides methods to compare versions:

Method Description

atLeast(String version)

Returns true if the Mule runtime version is equal to or greater than the specified version.

atLeastBase(String version)

Returns true if the base version (ignoring patch level) is equal to or greater than the specified version.

The runtime version is constant across your module, so @RuntimeVersion applies only at the field level. Centralize your version-dependent logic in a shared field rather than checking in every operation.

Call New Methods in Existing APIs

SDK APIs can add new methods in later versions. If you call a method that doesn’t exist on an earlier Mule runtime version, you get a NoSuchMethodError.

The SDK doesn’t introspect which methods your code actually calls. Even if a method has @MinMuleVersion("4.12.0"), using it doesn’t automatically raise your component’s Minimum Mule Version. You are able to deploy a module to earlier versions where the method doesn’t exist. For this reason, you must check the Mule runtime version before calling new methods, and provide fallback behavior for older versions.

Example: Using a New Method with Fallback

The following example shows how to conditionally call a method that exists in Mule 4.12.0 and later:

import org.mule.runtime.api.meta.MuleVersion;
import org.mule.sdk.api.annotation.RuntimeVersion;
import org.mule.sdk.api.runtime.streaming.StreamingHelper;

public class MyOperations {

  @RuntimeVersion
  private MuleVersion runtimeVersion;

  public void processStream(InputStream stream, StreamingHelper streamingHelper) {
    if (runtimeVersion.atLeast("4.12.0")) {
      // Use new reset() method available in 4.12.0
      streamingHelper.reset(stream);
    } else {
      // Implement fallback for older runtimes where reset() doesn't exist
      if (stream instanceof Cursor) {
        ((Cursor) stream).seek(0);
      } else {
        stream.reset();
      }
    }
  }
}

If no fallback is possible, explicitly annotate your operation with @MinMuleVersion to restrict it to compatible versions.

Use Newer APIs Without Raising Minimum Version

If you use a newer API but provide fallback behavior for older Mule runtime versions, you can prevent that API from raising your component’s Minimum Mule Version. Combine Mule version checking with @DoNotEnforceMinMuleVersion to keep your component available on earlier versions while using new features when available.

import org.mule.runtime.api.meta.MuleVersion;
import org.mule.sdk.api.annotation.DoNotEnforceMinMuleVersion;
import org.mule.sdk.api.annotation.RuntimeVersion;

public class MyOperations {

  @RuntimeVersion
  private MuleVersion runtimeVersion;

  public void myOperation(@DoNotEnforceMinMuleVersion NewFeatureType input) {
    if (runtimeVersion.atLeast("4.12.0") && input != null) {
      // Use new feature when available
    } else {
      // Fallback behavior for earlier versions
    }
  }
}

The input != null check is necessary because parameters with types from org.mule.sdk.api resolve to null on earlier versions that don’t recognize the type. By combining the version check with @DoNotEnforceMinMuleVersion, you:

  • Prevent the API from raising your component’s Minimum Mule Version

  • Safely use the feature on later Mule versions

  • Provide fallback behavior when the feature isn’t available

Best Practices for Forward-Compatible Code

Follow these guidelines when implementing version-dependent behavior:

  • Check versions before calling new methods

    Failing to do so causes NoSuchMethodError at runtime.

  • Centralize version checks

    Use a shared field annotated with @RuntimeVersion rather than checking in every method.

  • Test on multiple Mule runtime versions

    Verify your fallback logic works correctly on the earliest Mule version you support.

  • Document runtime-specific behavior

    If a feature behaves differently on earlier versions, document this for your users.