Accepted
Java SDK consumers span both server-side Java applications and Android apps. Both need async execution options, but Android has strict threading requirements (no blocking on the main thread). Options considered:
- Futures / CompletableFuture — Java 8+, but awkward on Android and not reactive.
- Plain callbacks — simple, but no composition; requires manual thread management.
- RxJava — well-established reactive library with Android support, first-class Retrofit2 adapter.
The original implementation used RxJava 1.x (see git history: "RxJava v1.0.11", "RxJava v1.0.13"), later upgraded to RxJava2.
Use RxJava2 (2.2.5) as the async execution substrate, exposed to SDK consumers via CMACallback<T> (a simplified callback interface). Internally:
- Each module method creates an
Observable<T>viaRxExtensions. - The observable subscribes on an I/O scheduler (
Schedulers.io()). - Results are delivered to the provided
Executor(defaulting to a cached thread pool), which marshalsonSuccess/onFailureto the callback.
Consumers do not interact with RxJava directly — they use the CMACallback<T> interface. RxJava is an implementation detail.
- Enables: Decoupled thread management; easy Retrofit2 integration via
RxJava2CallAdapterFactory; subscribers can be cancelled. - Requires:
rxjavaandretrofit2:adapter-rxjava2as runtime dependencies. - Hidden from consumers: The RxJava API surface is internal — callers only see
CMACallback. This keeps the public API simple and allows future migration to a different async model. - Default
onFailure()is empty: A common footgun — callers who don't override it silently swallow errors. See AGENTS.md sharp edges.