Usage

About

In enterprise-grade applications, usage of RestTemplate is often abstracted, standardized, and injected as a dependency to ensure reusability, testability, and maintainability.

HTTP Methods in RestTemplate

HTTP Method

RestTemplate Method

Purpose / Description

Typical Usage

GET

getForObject(String url, Class<T>)

Retrieves a resource and maps the response body to the given class.

Fetching a customer by ID, getting configuration values, etc.

getForEntity(String url, Class<T>)

Same as above but gives access to full ResponseEntity (headers, status, body).

When response metadata like headers or status codes matter.

POST

postForObject(String url, Object, Class<T>)

Sends an object as request body and receives a response mapped to the given class.

Creating a new resource like customer, transaction, etc.

postForEntity(String url, Object, Class<T>)

Similar to above but returns ResponseEntity.

When we need to access response headers or status along with body.

PUT

put(String url, Object)

Updates a resource; does not return anything.

Updating customer details, modifying order info.

DELETE

delete(String url)

Deletes the resource at the specified URL.

Deleting a user, removing a product from cart, etc.

PATCH

Not directly supported (manual exchange)

PATCH is not directly supported; must use exchange() method with HttpMethod.PATCH.

Partial updates to resources, such as modifying specific fields (e.g., status).

HEAD

Not directly supported (use exchange)

Used to fetch headers without the body. Often used for metadata checks.

Checking if a resource exists without downloading it.

OPTIONS

Not directly supported (use exchange)

To determine allowed operations on a resource.

Checking CORS rules or supported methods.

Any

exchange(String url, HttpMethod, HttpEntity, Class<T>)

General-purpose method to perform any HTTP request with full control.

Advanced use cases needing headers, custom methods, etc.

Any (generic)

execute(String url, HttpMethod, RequestCallback, ResponseExtractor<T>)

Lowest-level API for full flexibility.

Rarely used; suited for streaming, low-level customization.

Centralized Configuration Using @Bean

In most large-scale applications, RestTemplate is defined as a Spring-managed bean to ensure consistent configuration across the application. Timeouts, interceptors, and error handling are typically set once and reused.

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder
                .setConnectTimeout(Duration.ofSeconds(5))
                .setReadTimeout(Duration.ofSeconds(10))
                .additionalInterceptors(new LoggingInterceptor())
                .build();
    }
}

This ensures:

  • Centralized control over timeouts

  • Reusable interceptors (e.g., logging, authentication headers)

  • Consistent error behavior

Dependency Injection and Reuse in Services

Avoid creating RestTemplate instances manually. In real-world services, it is autowired and reused.

@Service
public class CustomerService {

    private final RestTemplate restTemplate;

    @Autowired
    public CustomerService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public CustomerDTO fetchCustomerById(String customerId) {
        String url = "https://customer-service/api/customers/{id}";
        return restTemplate.getForObject(url, CustomerDTO.class, customerId);
    }
}

This is how services talk to other services over HTTP. The URL is often externalized using @Value or a config server.

Using Exchange for Full Control

When we need to control HTTP method, headers, request body, or inspect the full response (status code, headers, body), the exchange() method is used.

public PaymentResponse initiatePayment(PaymentRequest paymentRequest) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setBearerAuth(tokenService.getAccessToken());

    HttpEntity<PaymentRequest> entity = new HttpEntity<>(paymentRequest, headers);

    ResponseEntity<PaymentResponse> response = restTemplate.exchange(
            "https://payment-service/api/payments",
            HttpMethod.POST,
            entity,
            PaymentResponse.class
    );

    return response.getBody();
}

This approach mirrors real-world APIs where headers, tokens, and status need to be fully managed.

Handling Path and Query Parameters

For APIs with dynamic segments or filters:

String url = "https://orders-service/api/orders/{orderId}";
OrderDTO order = restTemplate.getForObject(url, OrderDTO.class, "ORD123");

Or with query parameters:

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://orders-service/api/orders")
        .queryParam("status", "PENDING")
        .queryParam("limit", 10);

OrderListResponse orders = restTemplate.getForObject(builder.toUriString(), OrderListResponse.class);

Last updated