---
source_url: https://www.pubnub.com/docs/sdks/kotlin/migration-guides/kotlin-v9-migration-guide
title: Java/Kotlin SDK 9.0.0 migration guide
updated_at: 2026-05-29T11:11:15.939Z
sdk_name: PubNub Kotlin SDK
sdk_version: 13.4.0
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Java/Kotlin SDK 9.0.0 migration guide

PubNub Kotlin SDK, use the latest version: 13.4.0

Install:

```bash
Add PubNub dependency to your build@13.4.0
```

The 9.0.0 release of Java and Kotlin SDKs unifies both codebases. From now on, the SDKs are versioned and released together, so clients using both receive features and fixes at the same time.

We kept the API surface close to earlier releases. To upgrade to the [Java](https://www.pubnub.com/docs/sdks/java) or [Kotlin](https://www.pubnub.com/docs/sdks/kotlin) SDK v9.0.0, you make a few focused updates in your application code for PubNub usage.

## Create the PubNub object

Use `PNConfiguration.builder()` to configure, then `PubNub.create()` to instantiate the client. This approach replaces direct constructor use.

### Legacy Java SDK

```java
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "yourSubscribeKey");
configBuilder.publishKey("myPublishKey");
PubNub pubnub = PubNub.create(configBuilder.build());
```

### Legacy Kotlin SDK

```kotlin
val builder = PNConfiguration.builder(UserId("myUniquesUserID"), "subscribeKey") {
    publishKey = "publishKey"
}
val pubnub = PubNub.create(builder.build())
```

### New Java SDK

```java
PubNub pubnub = PubNub.create(new PNConfiguration(...))
```

### New Kotlin SDK

```kotlin
var pubnub = PubNub.create(PNConfiguration(...))
```

## Async result callback

The asynchronous API callback signature has changed. `PNStatus` is no longer provided in the `async` callback. The new `Result` type gives you either the successful value or a `PubNubException`, with no null checks or type mismatches.

The sections below show legacy (< v9.0.0) and v9.0.0 signatures and a recommended usage pattern for getting results from API calls.

### Function signature

#### Legacy Java SDK

```java
public void async(@NotNull final PNCallback<Output> callback)

public interface PNCallback<@Nullable X> {
   void onResponse(@Nullable X result, @NotNull PNStatus status);
}
```

#### Legacy Kotlin SDK

```kotlin
fun async(callback: (result: Output?, status: PNStatus) -> Unit)
```

#### New Java SDK

```java
public void async(@NotNull final Consumer<Result<Output>> callback)

public interface Consumer<Result<Output>> {
    void accept(Result<Output> result);
}
```

#### New Kotlin SDK

```kotlin
fun async(callback: (Result<Output>) -> Unit)
```

### Usage pattern

#### Legacy Java SDK

```java
pubnub.publish(...).async((result, status) -> {
    if (status.isError()) {
        // handle error either by looking at the exception, error or category:
        status.getErrorData()
        status.getCategory()
    } else {
        // handle success
        System.out.println(
            "Sent message with timetoken: " + result.getTimetoken()
        );

    }
});
```

#### Legacy Kotlin SDK

```kotlin
pubnub.publish(...).async { result, status -> 
    if (status.isError()) {
        // handle error either by looking at the exception, error or category:
        status.exception
        status.category
    } else {
        // handle success
       println(
            "Sent message with timetoken: " + result!!.timetoken
        )
    }
}
```

#### New Java SDK

```java
pubnub.publish(...).async(result -> {
    result.onFailure((PubNubException exception)  -> {
        // handle error
        System.err.println("Got exception: " + exception);
    }).onSuccess(pnPublishResult -> {
        // handle success
        System.out.println(
            "Sent message with timetoken: " + pnPublishResult.getTimetoken()
        );
    });
});

// alternative version
pubnub.publish(...).async(result -> {
    if (result.isFailure()) {
        // handle error
        System.err.println("Got exception: " + result.exceptionOrNull());
    } else {
        // handle success
        System.out.println(
            "Sent message with timetoken: " + result.getOrNull().getTimetoken()
        );
    }
});
```

#### New Kotlin SDK

```kotlin
pubnub.publish(...).async { result -> 
    result.onFailure { exception ->
        // handle error
       println("Got exception: " + exception);
    }.onSuccess { pnPublishResult ->
        // handle success
       println(
            "Sent message with timetoken: " + pnPublishResult.timetoken
        )
    }
}

// alternative version
pubnub.publish(...).async { result -> 
    if (result.isFailure()) {
        // handle error
        println("Got exception: " + result.exceptionOrNull())
    } else {
        // handle success
       println(
            "Sent message with timetoken: " + result.getOrNull().getTimetoken()
        )
    }
}
```

## Statuses

`PNStatus` is still used for subscribe calls, while a `Result` class is used for other requests. The set of possible statuses is reduced and standardized across SDKs.

### Subscribe requests

For subscribe requests, use the `PNStatus` object. To get its value, see [StatusListener](https://www.pubnub.com/docs/sdks/java/api-reference/publish-and-subscribe#add-connection-status-listener).

```kotlin
// Adding the status listener to the PubNub client
pubnub.addListener(object : StatusListener() {
    override fun status(pubnub: PubNub, status: PNStatus) {
        // This block is executed asynchronously for each status update
        println("Connection Status: ${status.category}")
    }
})
```

### Error statuses

For initial subscribe failures, you receive a status with category `PNConnectionError`. For failures after an initial successful connection (after `PNConnected`), the status is typically `PNUnexpectedDisconnectCategory`.

:::tip Current statuses
For more on current statuses, see [Status Events](https://www.pubnub.com/docs/sdks/java/status-events) in the Java SDK and [Status Events](https://www.pubnub.com/docs/sdks/kotlin/status-events) in the Kotlin SDK.
:::

In all error cases:

* The `error` field is `true` in `PNStatus`.
* The `exception` field contains the exception that caused the disconnect.
* There are no dedicated error categories. To get details, use the `exception` field.

#### Access Manager

Access Manager errors now appear as follows:

```java
PubNubException(errorMessage={"message": "Forbidden", "payload": {"channels": ["abc"]}, "error": true, "service": "Access Manager", "status": 403},
    pubnubError=PubNubError(name=HTTP_ERROR, code=103, message='HTTP Error. Please check network connectivity.'),
    jso={"message":"Forbidden","payload":{"channels":["abc"]},"error":true,"service":"Access Manager","status":403},
    statusCode=403,
    affectedChannels=[abc])
```

### Non-subscribe requests

For non-subscribe requests like publish, you now receive a `Result` (success or failure) instead of `PNStatus`.

#### Success and failure handling

On success, `Result` delivers the returned value (for example, `PNPublishResult`). On failure, it delivers a `PubNubException`.

#### Publish success and failure handling example

```kotlin
pubNub.publish("abc", "test").async {
    it.onSuccess { result: PNPublishResult ->
        println(result)
    }.onFailure { exception: PubNubException ->
        println(exception)
    }
}
```

## Minor API differences

If you depended on internal classes or methods, adjust your code as follows:

* Internal classes are no longer on the compile classpath. Avoid accessing or using them in your code.
* All public classes are in the `com.pubnub.api` package. Internal ones are in `com.pubnub.internal`. Avoid using internal classes because they can change or be removed.
* If you used the `Endpoint` class in Kotlin, it previously took two type parameters: `Endpoint<Input, Output>`. Because access to internal `Input` classes is restricted, the signature is now `Endpoint<Output>`.

If you see other impacts to Java or Kotlin SDK functionality, [contact support](https://support.pubnub.com/hc/en-us/requests/new) and we’ll help you move forward quickly.

## Terms in this document

* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.