Building a Java application with RxJava in NetBeans

Reactive streams have quietly become the default way for Java teams in Australia to wrangle asynchronous data flows, and NetBeans IDE remains a familiar companion for many of them. From Brisbane fintechs ingesting market data to back-office services in Melbourne's Docklands, the appeal is simple: compose event pipelines without drowning in callbacks.

RxJava fits this picture well. The library offers Observable, Flowable, Single and Completable types that map cleanly onto REST endpoints, message queues or websocket feeds. Combined with NetBeans' code completion, refactoring and integrated debugger, wiring reactive operators feels far more forgiving than juggling raw threads.

A few Australian realities shape how the code performs. Latency from ap-southeast-2 (Sydney) to overseas regions can swing through the day, and a pipeline that looks fine at 9 am AEST may behave differently when the NBN link at the office hits its evening peak. Scheduler choices in RxJava directly affect how those edges surface, which is why thread configuration deserves as much attention as the operators themselves.

This guide walks through creating a small reactive service in NetBeans, from dependency setup to a runnable JAR. It points to profiling tips, error handling patterns and a few related posts on the site.

Adding RxJava to a Maven project

Start a new Java Application project through File → New Project → Java with Maven. NetBeans generates a standard pom.xml and indexes it against the local repository, which in most Australian setups already mirrors Maven Central through a corporate Nexus or Artifactory instance. Add the latest 3.x dependency for io.reactivex.rxjava3:rxjava and the IDE will flag any version conflicts before a build is attempted.

Gradle teams can drop the equivalent into build.gradle. Either way, opening NetBeans' dependency graph view after the library resolves confirms that reactive-streams and jsr305 are pulled in correctly. A flat-white break is a good time to glance over the tree.

Modeling event sources with Observable and Flowable

The first design question is usually which reactive type suits the source. Observable is fine when the consumer keeps up, but Flowable is the safer default for any pipeline ingesting more than a handful of items per second, including HTTP responses and database cursors. NetBeans' go-to-symbol feature makes jumping from an operator to its declaration quick when the chain grows.

In a typical back-office tool, a Flowable might wrap a polling call to a transactional API, while a Single handles a one-shot lookup against a static configuration service. Using just(), fromCallable() and interval() for these cases keeps test code small and lets the IDE suggest the right consumer type inline.

Composing operators for business logic

Operators such as filter, map, flatMap and merge turn raw events into business outcomes. A common pattern is fetching a customer record, fanning out to two parallel enrichment calls - one against an internal CRM, one against an external credit bureau - then merging results into a single record. NetBeans' rename refactor handles renaming across lambdas and method references without breaking the chain.

Breaking long chains into small static methods pays off. The IDE's "Find Usages" then surfaces every place a transformation is reused, making duplication between reactive services easier to spot.

Picking schedulers and managing threads

Schedulers are where most production incidents originate. subscribeOn controls where the source emits, while observeOn switches threads downstream. Schedulers.io() suits blocking I/O, Schedulers.computation() fits CPU-bound work, and Schedulers.trampoline() lets queued work run on the current thread for testing. NetBeans' debugger shows thread names in call site tooltips, making scheduler mistakes obvious the first time a chain executes.

For a Sydney-hosted service ingesting partner feeds from Singapore, pinning network calls to Schedulers.io() and enrichment logic to Schedulers.computation() keeps CPU cores busy without starving the event loop. A quick smoke test using the CPU profiling walkthrough catches scheduler misconfigurations before they reach staging.

Error handling, retries and backpressure

Reactive pipelines fail in interesting places. onErrorReturn, onErrorResumeNext and retryWhen offer fine-grained recovery, while backpressure strategies (BUFFER, DROP, LATEST, MISSING) decide what happens when a consumer cannot keep up. For services operating under the Privacy Act 1988 and the Notifiable Data Breaches scheme, log retry attempts with enough context to demonstrate responsible handling without capturing sensitive payload data.

NetBeans' conditional breakpoints help here. Setting a breakpoint that fires only on a specific exception type lets a developer confirm the recovery path without rerunning the whole pipeline. For distributed services, the guide on remote debugging over SSH is handy when reproducing errors in a staging environment.

Testing reactive streams inside NetBeans

JUnit 5 plus RxJava's TestScheduler makes deterministic testing straightforward. NetBeans' test runner shows passes and failures inline, and the "Debug Test File" action drops a developer into the scheduler's virtual time. For projects tracking the Australian Cyber Security Centre's Essential Eight, wiring the suite into NetBeans' continuous build action keeps security regressions visible early.

Advance the TestScheduler by explicit increments and assert on emitted values at each step rather than relying on real time. The IDE's variable inspection shows the exact subscriber state during a paused virtual clock, making flaky timing assertions easier to diagnose.

Profiling, debugging and packaging the final JAR

Once the service runs cleanly, the NetBeans Profiler is the fastest way to confirm that thread allocation and GC pauses match expectations. Watching allocation hotspots after a representative load run often surfaces scheduler mistakes that escape unit tests. Package the artefact with the Maven Shade plugin for a fat JAR, or ship a thin JAR with dependencies separately if the runtime image is already provisioned. The build artefact notes in the NetBeans Blog archive have older write-ups worth scanning for platform-specific tips, especially for teams still supporting AIX or Solaris nodes alongside modern Linux fleets.

Practical recommendations for keeping RxJava projects healthy

  • Pin the RxJava version in the build file and revisit it quarterly, since breaking changes between minor releases do happen.
  • Prefer Flowable over Observable whenever the source can emit more than one item per second or when backpressure matters.
  • Use TestScheduler for any test that depends on timing and avoid Thread.sleep in reactive unit tests.
  • Log retry counts and reasons in a structured format that excludes payload data, to stay aligned with the Privacy Act.
  • Profile a representative workload in the NetBeans Profiler before each major release rather than waiting for slowdowns to surface.
  • Keep operator chains short and named so the next developer, perhaps a contractor arriving from interstate, can read the pipeline without a whiteboard.