Spring Boot RestTemplate GET Example

Learn Spring Boot RestTemplate GET calls with runnable examples for getForObject, getForEntity, custom headers, and missing resources.

Junit Test Results

Use RestTemplate.getForObject() when you need the response body, and getForEntity() when you also need the HTTP status and headers. Both methods send a GET request and map a JSON response to a Java type. If the request needs custom headers, exchange() lets you supply them.

This tutorial uses Spring Boot 4.1.2 and Java 17 or later. An inventory service reports the available quantity of a product at a warehouse. We will retrieve that stock record, inspect the full HTTP response, send a request ID header, and see what a missing product returns.

1. Add the Dependencies

The application exposes a small HTTP endpoint with Spring MVC. The REST client starter supplies RestTemplate, and the test starter lets the example call a running local server. The complete Maven file is in the source repository.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>4.1.2</version>
  <relativePath/>
</parent>

<properties><java.version>17</java.version></properties>

<dependencies>
  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webmvc</artifactId></dependency>
  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-restclient</artifactId></dependency>
  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webmvc-test</artifactId><scope>test</scope></dependency>
</dependencies>

Spring Boot does not require a special annotation on RestTemplate. Declare a bean so the client service can receive it through constructor injection:

@Bean
RestTemplate restTemplate() {
    return new RestTemplate();
}

The example creates one client instance for the application. Each request still creates a separate HTTP exchange.

2. Expose a Stock Resource

The URL /inventory/BOOK-42?warehouse=west identifies a product by SKU and selects a warehouse with a query parameter. The response record has the SKU, warehouse and available quantity. The controller returns 404 for an unknown SKU, so the client can distinguish a missing resource from an in-stock product with zero quantity.

@RestController
public class InventoryController {
    public record Stock(String sku, String warehouse, int available) {}

    @GetMapping("/inventory/{sku}")
    ResponseEntity<Stock> stock(@PathVariable String sku,
                                @RequestParam(defaultValue = "main") String warehouse,
                                @RequestHeader(value = "X-Request-Id", required = false) String requestId) {
        if (!sku.equals("BOOK-42")) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok()
                .header("X-Request-Id", requestId == null ? "none" : requestId)
                .body(new Stock(sku, warehouse, warehouse.equals("west") ? 4 : 12));
    }
}

The quantities are fixed so the example needs no database. The optional request ID appears in the response to make the header example observable. The real client calls this controller over HTTP; it does not invoke the stock() method directly.

3. Read the Body with getForObject()

For a normal stock lookup, the caller only needs the JSON response body mapped to Stock. Build the URL as a URI so the SKU is a path segment and the warehouse is a query parameter. UriComponentsBuilder encodes their values before the client sends the request.

URI uri = UriComponentsBuilder.fromUriString(baseUrl)
        .pathSegment("inventory", sku)
        .queryParam("warehouse", warehouse)
        .build()
        .encode()
        .toUri();

InventoryController.Stock stock = restTemplate.getForObject(
        uri, InventoryController.Stock.class);

With sku = "BOOK-42" and warehouse = "west", the local test receives a Stock record with available = 4. Spring’s JSON message converter reads the response body and creates that record. The method returns the mapped body, so its return type has no place for the HTTP status or response headers.

4. Read Status and Headers with getForEntity()

Suppose the caller also needs to confirm the status or inspect a response header. getForEntity() returns a ResponseEntity containing the mapped Stock value and all three parts of the HTTP response:

ResponseEntity<InventoryController.Stock> response = restTemplate.getForEntity(
        uri, InventoryController.Stock.class);

System.out.println(response.getStatusCode());
System.out.println(response.getHeaders().getFirst("X-Request-Id"));
System.out.println(response.getBody().available());

For the main warehouse, the verified response is HTTP 200, header X-Request-Id: none, and an available quantity of 12. The header value none is produced by this example controller when the request omits the optional header; it is not a general Spring default.

Need Method Return value
Mapped response body getForObject() Stock
Status, headers and mapped body getForEntity() ResponseEntity containing Stock
Custom request headers exchange() ResponseEntity containing Stock

Choose the smallest method that gives the caller the information it uses. The first two calls issue separate GET requests if both appear in the same program.

5. Send a Request Header with exchange()

The inventory service accepts an optional X-Request-Id header to associate its response with a request. getForObject() and getForEntity() do not take an HttpEntity argument for custom request headers. exchange() accepts the HTTP method and a request entity, so it fits this requirement.

HttpHeaders headers = new HttpHeaders();
headers.set("X-Request-Id", "trace-123");

ResponseEntity<InventoryController.Stock> response = restTemplate.exchange(
        uri,
        HttpMethod.GET,
        new HttpEntity<>(headers),
        InventoryController.Stock.class);

The test calls the west warehouse and verifies that the server echoes trace-123 in its response header while the body still reports four units. The HttpEntity above has headers and no request body, which is appropriate for this GET.

6. Handle a Missing Resource

An unknown SKU makes the server return HTTP 404. With the default RestTemplate error handler, the client call throws HttpClientErrorException.NotFound. It does not return a Stock value with zero units, and a caller should not treat those situations as equivalent.

try {
    InventoryController.Stock stock = restTemplate.getForObject(
            missingSkuUri, InventoryController.Stock.class);
} catch (HttpClientErrorException.NotFound ex) {
    System.out.println(ex.getStatusCode()); // 404 NOT_FOUND
}

The integration test makes this request against the running local server and checks the exception’s status. If the application wants to display a friendly missing-product message, catch the exception at the boundary that translates HTTP failures into that message. Other 4xx and 5xx responses need their own handling policy. For stalled connections and reads, see RestTemplate timeout configuration.

7. Frequently Asked Questions

7.1. Does getForObject() return null for HTTP 404?

No. The default error handler treats a 404 response as an error and raises HttpClientErrorException.NotFound. A successful response with an empty body is a different case and may yield null.

7.2. Is RestTemplate the recommended client for new Spring Boot code?

The current Spring Framework REST client reference describes RestTemplate as deprecated in favor of RestClient. This example remains useful when maintaining an application that already uses RestTemplate. For a new synchronous client, start with RestClient and follow the current reference.

7.3. Can I send query parameters without concatenating strings?

Yes. UriComponentsBuilder adds each path segment and query parameter before encoding the URI. That keeps the query structure separate from user-supplied values and avoids errors caused by manually assembling a URL.

8. Conclusion

Use getForObject() for a mapped body, getForEntity() when status or headers matter, and exchange() when the request needs custom headers. A missing resource raises an exception under the default error handler, so handle it separately from a valid stock record with zero available units. The example’s four integration tests cover each of those paths.

The complete runnable example is in the Spring Boot RestTemplate GET project folder.

Leave a Comment

  1. If we are sending encoded email id in url. what will be mandatory headers method we need to call?

    Thanks in advance

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.