Skip to main content
Version: v2.4.0-0.14.0

Default Transformers

This guide covers the default transformers provided by the plugin and how to use them effectively.

Overview​

Transformers are the core components that define how suspend functions are transformed for different platforms. The plugin provides several built-in transformers that cover the most common use cases.

note

The default transformers depend on the annotation and runtime dependencies provided by the plugin. Make sure you include them in your configuration before using default transformers.

JVM Transformers​

JVM Blocking Transformer​

The JVM Blocking transformer generates blocking variants of suspend functions using runBlocking.

Configuration​

suspendTransformPlugin {
transformers {
// Way 1: Simple addition
addJvmBlocking()

// Way 2: Using configuration object
addJvm(SuspendTransformConfigurations.jvmBlockingTransformer)

// Way 3: Using platform-specific addition
add(
TargetPlatform.JVM,
SuspendTransformConfigurations.jvmBlockingTransformer
)
}
}

Usage​

class ApiService {
@JvmBlocking
suspend fun fetchData(): String {
delay(1000)
return "Data fetched"
}
}

Key Features​

  • Default Generated Function Suffix: Blocking
  • Return Type: Same as the original function
  • Runtime Function: $runInBlocking$ (based on kotlinx.coroutines.runBlocking)

Lifecycle And Dispatcher​

The generated blocking bridge is only intended for Java-style blocking interop. It blocks the calling thread until the suspend function completes. Thread interruption cancels the bridge and is reported as InterruptedException.

The default runtime uses runBlocking(Dispatchers.IO). This keeps the suspend body off the calling thread after dispatch and is a conservative default for possibly blocking work, but the caller is still blocked. Avoid generated blocking bridges from coroutines, UI/event-loop threads, or other thread-limited execution paths.

Use a custom transformer/runtime when a specific dispatcher, transaction context, MDC, or thread affinity is required.

Mark Annotation​

@JvmBlocking provides some properties to change the default values and customize the generated function results.

baseName​

baseName represents the base name of the generated function. By default, it is empty (""). If the value is empty, it means using the same value as the original function.

The final function name of the generated function is baseName + suffix.

suffix​

suffix represents the suffix of the generated function. By default, it is Blocking.

asProperty​

asProperty represents whether to generate a property instead of a function. By default, it is false.

suspend fun foo(): T = ...

// Generated
@Api4J
val fooBlocking: T
get() = runInBlocking { foo() }
note

If asProperty is true, the function cannot have parameters.

markName​

Refer to Mark Name.

JVM Async Transformer​

The JVM Async transformer generates asynchronous variants using CompletableFuture.

Configuration​

suspendTransformPlugin {
transformers {
// Way 1: Simple addition
addJvmAsync()

// Way 2: Using configuration object
addJvm(SuspendTransformConfigurations.jvmAsyncTransformer)

// Way 3: Using platform-specific addition
add(
TargetPlatform.JVM,
SuspendTransformConfigurations.jvmAsyncTransformer
)
}
}

Usage​

class ApiService {
@JvmAsync
suspend fun fetchData(): String {
delay(1000)
return "Data fetched"
}
}

Key Features​

  • Default Generated Function Suffix: Async
  • Return Type: CompletableFuture<out T> where T is the original return type
  • Runtime Function: $runInAsync$
  • Scope Handling: Uses the current CoroutineScope if available, otherwise GlobalScope

Lifecycle And Cancellation​

If the receiver is a CoroutineScope, the generated bridge launches the coroutine in that scope. Otherwise, the default runtime uses GlobalScope.

Cancelling the returned CompletableFuture cancels the coroutine. Dropping a long-running future without cancelling it does not stop the underlying work, so Java callers should keep and cancel the returned future when the operation is no longer needed.

Mark Annotation​

@JvmAsync provides some properties to change the default values and customize the generated function results.

baseName​

baseName represents the base name of the generated function. By default, it is empty (""). If the value is empty, it means using the same value as the original function.

The final function name of the generated function is baseName + suffix.

suffix​

suffix represents the suffix of the generated function. By default, it is Async.

asProperty​

asProperty represents whether to generate a property instead of a function. By default, it is false.

suspend fun foo(): T = ...

// Generated
@Api4J
val fooAsync: CompletableFuture<out T>
get() = runInAsync { foo() }
note

If asProperty is true, the function cannot have parameters.

markName​

Refer to Mark Name.

JVM Reactive Transformer​

Version 0.14.0

The JVM Reactive transformer generates Reactive Streams Publisher variants.

Configuration​

suspendTransformPlugin {
transformers {
// Way 1: Simple addition
addJvmReactive()

// Way 2: Using configuration object
addJvm(SuspendTransformConfigurations.jvmReactiveTransformer)
}
}

Usage​

@OptIn(ExperimentalJvmApi::class)
class ApiService {
@JvmReactive
suspend fun fetchData(): String? = null
}

Key Features​

  • Default Generated Function Suffix: Reactive
  • Return Type: Publisher<T & Any> where T is the original return type
  • Runtime Function: $runInReactive$
  • Null Handling: null results complete empty
  • Scope Handling: the generated call may pass a CoroutineScope, but the default runtime keeps the parameter only for generated bridge compatibility and future runtime strategies. It does not use it as a coroutine parent or dispatcher source.

Lifecycle And Cancellation​

The returned Publisher is cold: the suspend block starts when a subscriber subscribes. Cancelling the Reactive Streams Subscription cancels the publisher coroutine.

Reactive scheduling is not configured by the default bridge. Use the caller's reactive chain, withContext inside the suspend function, or a custom transformer/runtime for dispatcher or lifecycle requirements.

note

This transformer requires org.reactivestreams.Publisher and org.jetbrains.kotlinx:kotlinx-coroutines-reactive on the JVM classpath. These dependencies are not added automatically by addJvmReactive(); add them to the user JVM project or source set.

JavaScript Transformers​

JS Promise Transformer​

The JS Promise transformer generates Promise-based variants for JavaScript interoperability.

Configuration​

suspendTransformPlugin {
transformers {
// Way 1: Simple addition
addJsPromise()

// Way 2: Using configuration object
addJs(SuspendTransformConfigurations.jsPromiseTransformer)

// Way 3: Using platform-specific addition
add(
TargetPlatform.JS,
SuspendTransformConfigurations.jsPromiseTransformer
)
}
}

Usage​

class ApiService {
@JsPromise
suspend fun fetchData(): String {
delay(1000)
return "Data fetched"
}
}

Key Features​

  • Default Generated Function Suffix: Async
  • Return Type: Promise<T> where T is the original return type
  • Runtime Function: $runInAsync$

Mark Annotation​

@JsPromise provides some properties to change the default values and customize the generated function results.

baseName​

baseName represents the base name of the generated function. By default, it is empty (""). If the value is empty, it means using the same value as the original function.

The final function name of the generated function is baseName + suffix.

suffix​

suffix represents the suffix of the generated function. By default, it is Async.

asProperty​

asProperty represents whether to generate a property instead of a function. By default, it is false.

suspend fun foo(): T = ...

// Generated
@Api4Js
val fooAsync: Promise<T>
get() = runInAsync { foo() }
note

If asProperty is true, the function cannot have parameters.

markName​

Refer to Mark Name.

Convenience Functions​

Combined JVM Transformers​

suspendTransformPlugin {
transformers {
// Includes addJvmBlocking() and addJvmAsync()
useJvmDefault()
}
}

This is equivalent to:

suspendTransformPlugin {
transformers {
addJvmBlocking()
addJvmAsync()
}
}

addJvmReactive() is not included in useJvmDefault() and must be enabled explicitly.

Combined JS Transformers​

suspendTransformPlugin {
transformers {
// Includes addJsPromise()
useJsDefault()
}
}

All Default Transformers​

suspendTransformPlugin {
transformers {
// Includes all default transformers for all platforms
useDefault()
}
}

This is equivalent to:

suspendTransformPlugin {
transformers {
useJvmDefault() // JVM Blocking + JVM Async
useJsDefault() // JS Promise
}
}

Combining Multiple Annotations​

You can use multiple transformer annotations on the same function:

class ApiService {
@JvmBlocking
@JvmAsync
@JvmReactive
@JsPromise
suspend fun fetchData(): String {
delay(1000)
return "Data fetched"
}
}

This will generate:

  • fetchDataBlocking(): String (JVM)
  • fetchDataAsync(): CompletableFuture<out String> (JVM)
  • fetchDataReactive(): Publisher<String> (JVM)
  • fetchDataAsync(): Promise<String> (JS)