Skip to content

2.0 findings: release() migration note, JavaDoc coverage and device build() throws #1255

Open

Description

@sacOO7

These came up while validating the Pub/Sub 2.0 website docs against integration/v2 at f7f4363cd3caa0bed523c7751ebdcfbcb3c33221. They're grouped here so they can be triaged together. If you'd rather track any of them on its own, split it into a separate issue.

Summary

# Finding Priority Website docs depend on it? Recommendation
1 UPGRADING.md misses the release() change (now a checked exception and 90011) and two error-code fixes. The README, CONTRIBUTING and the 40019 LiveObjects error still name 1.x artifacts P1 Yes, in part: the 2.0 LiveObjects docs quote the 40019 message Add a release() section to UPGRADING, finish moving the README and CONTRIBUTING to 2.0 coordinates, and fix the 40019 message
2 The published JavaDoc covers only core. PubSubServer and PubSubDevice are missing, and the device javadoc jar is empty P2 Yes: the ably.com Java API reference will need to read this path for 2.0 Publish one aggregated reference: Javadoc for core and server, Dokka for device
3 PubSubDevice.ClientBuilder.build() throws a checked AblyException but doesn't declare it, so Java callers can't catch it by type P2 No Add @Throws(AblyException::class)

P1 = should be fixed before the 2.0 release · P2 = should be fixed soon · P3 = nice to have.

1. UPGRADING.md misses the release() and error-code changes; README, CONTRIBUTING and the 40019 error still name 1.x (P1)

What's wrong

The 2.0 code is in place, but the upgrade guide and several user-facing strings still describe 1.x:

  • UPGRADING.md doesn't say that Channels.release() now throws, and it doesn't mention two error-code fixes.
  • README.md is half-migrated: its install lines are for 1.x, but its sample is for 2.0.
  • CONTRIBUTING.md and the LiveObjects-missing error (40019) still name 1.x artifacts.

Evidence

release() is a source break that UPGRADING.md doesn't mention

  • On a realtime client, Channels.release() now declares throws AblyException. It throws 90011 (status 400) unless the channel is INITIALIZED, DETACHED or FAILED (PubSubRealtimeClient.java#L181, #L229-L233). In 1.x, release() detached the channel implicitly.

  • AblyException is a checked exception, so every existing Java call to release() fails to compile. Compiling c.channels.release("x") against the jars built at f7f4363c gives:

    Rel.java:1: error: unreported exception AblyException; must be caught or declared to be thrown
    
  • The release() Javadoc (#L171-L180) doesn't name 90011. The Kotlin adapter's KDoc does (Channels.kt#L47).

Two error-code fixes may reach users first in 2.0

Both were merged to main after 1.8.2 and are on integration/v2. If no further 1.x release ships them first, 2.0.0 is where users first see them, and the guide should say so:

README.md is half-migrated

The note at #L29-L31 says the install instructions still describe 1.x. The sample right below them already uses PubSubServer.realtimeClientBuilder() (#L84-L91), which doesn't exist in the artifact those install lines add. So code that follows the README as written doesn't compile.

The release-process version bump won't fix these lines, because they need new coordinates, not a new version number:

  • #L2: the version badge resolves io.ably/ably-java.
  • #L25: io.ably.pubsub:device is labelled "(aar)". It is a Kotlin Multiplatform artifact (device, device-jvm, device-android), and Maven users must depend on device-jvm (UPGRADING.md#L37-L39).
  • #L54 says "Android >=4.4 (API level 19)", but device has minSdk = 24. UPGRADING already says so at #L41-L43.
  • #L63-L80: the Maven and Gradle install lines are io.ably:ably-java:1.8.2.
  • #L139-L142: LiveObjects is installed as io.ably:liveobjects:1.8.2.

CONTRIBUTING.md

  • #L38-L48 says the library ships with the HttpURLConnection/Java-WebSocket engine by default, and shows how to switch to OkHttp using io.ably:ably-java. The build has defaulted to OkHttp for a while (core/build.gradle.kts#L27-L31); this text was already stale in 1.x. The coordinates are also 1.x.
  • #L238: ably-android-1.8.2.aar.

LiveObjects-missing error (40019)

RealtimeObject.java#L89 tells users to add runtimeOnly('io.ably:liveobjects:<ably-version>'). In 2.0 the plugin is io.ably.pubsub:liveobjects (UPGRADING.md#L45-L47).

A user who follows the message gets the 1.x plugin, whose implementation class is io.ably.lib.liveobjects.DefaultLiveObjectsPlugin. 2.0 looks for io.ably.pubsub.liveobjects.DefaultLiveObjectsPlugin (LiveObjectsPlugin.java#L89), so it still doesn't find the plugin, and the same error comes back.

History

Impact

  • Java users upgrading to 2.0 hit a compile error on release(). Nothing in the upgrade guide explains it or the new requirement to detach first.
  • The README is the first thing users read after the release, and its install lines contradict its sample.
  • The 2.0 LiveObjects docs quote the 40019 message, and following the message as written doesn't fix the error.

Recommendation

  • UPGRADING.md: add a release() section covering the checked exception, 90011, and calling detach() and waiting before release(). Add rows for 80017 and the code/statusCode fix, unless a 1.x release ships them first.
  • Javadoc: name 90011 in the release() Javadoc.
  • CHANGELOG: when the 2.0.0 entry is generated, call out the release() change as breaking.
  • README: update the badge, the artifact table, the Android requirement, the install lines (Gradle device/server, Maven device-jvm/server) and the LiveObjects install line. Then drop the "still describe 1.x" note.
  • CONTRIBUTING: update the engine section and the AAR line.
  • 40019 message: change it to io.ably.pubsub:liveobjects:<version>.

2. The published JavaDoc covers only core: PubSubServer and PubSubDevice are missing (P2)

What's wrong

The JavaDoc workflow uploads only the core module's output. So the published 2.0 reference doesn't include the classes users create clients with.

Evidence

  • .github/workflows/javadoc.yml#L36-L44 runs ./gradlew javadoc, but uploads only core/build/docs/javadoc.
  • The core javadoc covers src/main/java and ../lib/src/main/java (core/build.gradle.kts#L45-L50). Neither contains io.ably.pubsub.server or io.ably.pubsub.device.
  • ./gradlew javadoc does build server/build/docs/javadoc, with PubSubServer and its builders. That directory is never uploaded.
  • device is Kotlin Multiplatform, so it has no javadoc task, and the build has no Dokka. As a result:
    • PubSubDevice has no generated reference anywhere.
    • Its Maven javadoc jars are configured as empty (device/build.gradle.kts#L95, JavadocJar.Empty()). The built device-jvm-javadoc.jar contains only a manifest.

The preview that the workflow uploaded for the release PR shows the gap. https://sdk.ably.com/builds/ably/ably-pubsub-java/pull/1245/javadoc/ lists the http, realtime, types and liveobjects packages (among others), but has no io.ably.pubsub.server or io.ably.pubsub.device package. …/io/ably/pubsub/server/PubSubServer.html is not found.

Gradle output and preview status codes

In a worktree at f7f4363c:

$ ./gradlew javadoc --dry-run | grep ':javadoc'
:core:javadoc  :gradle-lint:javadoc  :liveobjects:javadoc  :network-client-core:javadoc
:network-client-default:javadoc  :network-client-okhttp:javadoc  :pubsub-adapter:javadoc  :server:javadoc  :uts:javadoc
$ ./gradlew :server:javadoc :core:javadoc
$ ls server/build/docs/javadoc/io/ably/pubsub/server/
PubSubServer.html PubSubServer.ClientBuilder.html PubSubServer.HttpClientBuilder.html PubSubServer.RealtimeClientBuilder.html …
$ ls core/build/docs/javadoc/io/ably/pubsub/server
ls: …: No such file or directory

The workflow uploaded this preview from the release PR head ba473268 on 2026-10-15. javadoc.yml hasn't changed since then.

https://sdk.ably.com/builds/ably/ably-pubsub-java/pull/1245/javadoc/index.html     200
…/io/ably/pubsub/realtime/PubSubRealtimeClient.html                                200
…/io/ably/pubsub/server/PubSubServer.html                                          403
…/io/ably/pubsub/device/PubSubDevice.html                                          403
allclasses-index.html packages: annotation debug http liveobjects platform push realtime transport types util   (no server, no device)

History

Impact

  • The README tells users not to depend on core directly. In 2.0, the supported way to create a client is PubSubServer.httpClientBuilder() / realtimeClientBuilder() or PubSubDevice.clientBuilder(), and the published reference shows none of them.
  • The workflow also runs on push to main. Today sdk.ably.com/builds/ably/ably-pubsub-java/main/javadoc/ serves the 1.x reference; once 2.0 merges, it becomes this core-only reference. That's the path the ably.com Java API reference will need to read for 2.0. (The ably.com reference still reads the pre-rename ably-java/ path today.)
  • IDEs show no documentation for io.ably.pubsub:device from Maven Central, because its javadoc jars are empty.

Recommendation

Either:

  • generate one aggregated reference covering core and server (Javadoc) and device (Dokka, which can also produce real javadoc jars for device), and upload that; or
  • upload each module's docs under its own path, and link them from the core overview page.

3. PubSubDevice.ClientBuilder.build() throws a checked AblyException but doesn't declare it (P2)

What's wrong

PubSubDevice.ClientBuilder.build() (PubSubDevice.kt#L411-L419) documents @throws io.ably.pubsub.types.AblyException in its KDoc, and it does throw it: it calls RealtimeClientFactory.create(...), which throws AblyException.

It isn't annotated with @Throws(AblyException::class), though. So the compiled method has no throws clause, and Java code can't catch the exception by type.

Evidence

try {
    PubSubRealtimeClient client = PubSubDevice.clientBuilder().key(key).build();
} catch (AblyException e) {   // error: exception AblyException is never thrown in body of corresponding try statement
}

The exception is real. For example, PubSubDevice.clientBuilder().autoConnect(false).build() with no auth options throws io.ably.pubsub.types.AblyException at runtime (code 40000, "No authentication parameters supplied").

The server door declares the same exception, so the same Java code compiles against io.ably.pubsub:server:

Compile and runtime output

Against the jars built at f7f4363c:

$ javac … src/DeviceBuild.java      # try { PubSubDevice.clientBuilder().key("a:b").build(); } catch (AblyException e) { }
DeviceBuild.java:5: error: exception AblyException is never thrown in body of corresponding try statement
$ javac … ctl/ServerBuild.java      # the same pattern on PubSubServer.realtimeClientBuilder()...build()
rc=0

At runtime, with no network (autoConnect(false), no auth):

caught io.ably.pubsub.types.AblyException checked=true code=40000 msg=java.lang.Exception: No authentication parameters supplied

The bytecode agrees: PubSubDevice$ClientBuilder.build() has no Exceptions: attribute, while both server build() methods declare throws io.ably.pubsub.types.AblyException.

History

  • This looks like an omission. build() came in with 686bdfd with the KDoc @throws but no @Throws. Later commits changed its KDoc and body without adding the annotation. The server door declares the exception.
  • The internal Kotlin adapter is out of scope on purpose. Its Channels.release() has the same shape, but leaving @Throws off there was a deliberate choice (Simon Woolf's reply at Make releasing a realtime channel that isn't detached an error (RTS4c-e) #1251 (comment)): that interface is shared by the REST and realtime clients, and none of the adapter's other throwing methods declare it. This issue covers only the public device entry point.

Impact

  • Java apps on io.ably.pubsub:device (Android apps written in Java, JVM desktop clients) can't handle a client-construction failure as AblyException. They have to catch Exception and cast. That's unlike the server door, and unlike what the KDoc says.
  • PubSubDevice.clientBuilder() is the only supported way to create a client on the device side, so every Java device app goes through this method.

Recommendation

  • Add @Throws(AblyException::class) to PubSubDevice.ClientBuilder.build(). It's available in common code.
  • Optionally, add a Java source compile test in the device module that catches AblyException around build(), so that a missing annotation fails the build.

Checklist

  • UPGRADING.md: release() section (checked exception, 90011, detach first), plus the 80017 and code/statusCode rows unless they ship in 1.x first. README, CONTRIBUTING and the 40019 message moved to 2.0 coordinates
  • Published JavaDoc includes server and device (and real device javadoc jars)
  • @Throws(AblyException::class) on PubSubDevice.ClientBuilder.build()

Related

┆Issue is synchronized with this Jira Task by Unito

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions