Building a REST client in Java with Spring RestTemplate and WebClient
Spring offers two popular approaches for consuming external APIs: the traditional, blocking RestTemplate and the newer, reactive WebClient. Both can be wired into a Spring Boot service and used to call REST endpoints, but they suit different workloads and team preferences.
In Australia, where fintechs in Sydney's CBD, Brisbane's startup scene, and Melbourne's innovation hubs routinely integrate with banks like CommBank, Westpac, and NAB, picking the right HTTP client matters. Many local teams also work with government data sets from data.gov.au or pull information from telco APIs such as Telstra's developer platform. The choice often comes down to whether the surrounding service is synchronous or built on reactive streams.
Setting up the Spring Boot project
Start by adding the necessary dependencies to a Spring Boot 3 project. For blocking calls, include spring-web, which provides RestTemplate as part of the core web stack. For reactive work, add spring-boot-starter-webflux, which brings in WebClient along with Reactor Netty.
A typical build.gradle snippet looks like implementation 'org.springframework.boot:spring-boot-starter-web' for the blocking client, and implementation 'org.springframework.boot:spring-boot-starter-webflux' for the reactive one. Australian developers working on projects with strict AEST deadline windows often prefer starter-webflux because it lets a single thread handle many concurrent calls, reducing the need to spin up large thread pools when scraping during peak trading hours.
Building requests with RestTemplate
RestTemplate has been part of Spring since version 3 and remains a familiar friend for teams that prefer straightforward, imperative code. The class provides convenient methods such as getForObject, postForEntity, and exchange for custom requests.
A typical call to a third-party API might look like:
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("https://api.example.com/prices", String.class);
Custom headers, timeouts, and message converters are configured through RestTemplateBuilder. Many Australian integrators still rely on RestTemplate when pulling reference data from older endpoints such as BPAY lookups or ASIC business registries, where the request volume is low and predictability matters more than throughput.
Moving towards WebClient
WebClient is the modern, non-blocking successor to RestTemplate and lives in the spring-webflux module. It returns Mono and Flux objects, allowing multiple requests to be composed and processed asynchronously.
A basic WebClient call looks like:
WebClient client = WebClient.create("https://api.example.com");
Mono<String> response = client.get().uri("/prices").retrieve().bodyToMono(String.class);
Because it runs on a Reactor Netty event loop, WebClient scales well under load. This is handy for services that aggregate data from many sources at once, such as a Melbourne-based logistics dashboard pulling freight quotes from multiple carriers simultaneously during morning peak.
Comparing the two clients
| Feature | RestTemplate | WebClient |
|---|---|---|
| Programming model | Synchronous, imperative | Asynchronous, reactive |
| Concurrency | One thread per request | Event-loop, non-blocking |
| Backpressure | Not supported | Supported through Reactor |
| Project status | Maintenance mode | Actively developed |
| Best fit | Simple CRUD, batch jobs | High-throughput, streaming APIs |
Both libraries can coexist in the same application, which gives teams flexibility during gradual migrations. RestTemplate still ships with Spring Framework, but new features are landing in WebClient rather than the older client.
Handling authentication and custom headers
Most enterprise endpoints require headers such as Authorization, Accept, or trace identifiers. With RestTemplate, headers are usually added through HttpHeaders objects passed to exchange or postForEntity. With WebClient, the equivalent is the default header setup on a WebClient.Builder instance.
Australian organisations often connect to open banking APIs that demand OAuth 2.0 flows, while government services exposed via data.gov.au sometimes only require API keys. WebClient handles OAuth refresh tokens elegantly inside a reactive chain, whereas RestTemplate can also do the job using an interceptor but feels less natural when chaining token refreshes.
Testing the REST client
Testing is straightforward with both clients. For RestTemplate, MockRestServiceServer from spring-test simulates HTTP responses without hitting the network. For WebClient, WireMock or MockWebServer lets the test emulate a remote endpoint, and the reactive nature means tests can use StepVerifier to assert Mono emissions.
A common pattern in Australian teams is to write contract tests against third-party sandboxes, which are sometimes slow or rate-limited during AEST business hours. Caching responses locally with Caffeine makes test suites reliable and quick, especially when developers are running CI from Sydney or Perth data centres.
Practical recommendations for production
- Use WebClient for new microservices that already run on WebFlux or that need to call many APIs in parallel.
- Keep RestTemplate for legacy modules or when the surrounding service is purely blocking and adding Reactor would complicate the code.
- Centralise HTTP client configuration in a
@Configurationclass so timeouts, connection pools, and tracing stay consistent. - Apply sensible timeouts: connectTimeout and readTimeout prevent a slow Australian endpoint from blocking threads indefinitely.
- Use Micrometer or OpenTelemetry instrumentation to observe call latency and error rates, especially when integrating with external partners.
- Cache stable reference data locally to reduce outbound calls during peak periods.
- Document fallback behaviour clearly so on-call engineers know what happens when an upstream provider goes down.