← Back to list

Different Ways to Consume REST APIs in Spring Boot Microservices

In Spring Boot, we can integrate external or internal services mainly using:

Vandana Vaishnav · 2026-05-04 14:45 · 0 claps · 5.8 min read
#microservices #spring-boot #resttemplate #webclient #feign
Open on Medium ↗

Different Ways to Consume REST APIs in Spring Boot Microservices

In Spring Boot, we can integrate external or internal services mainly using:

  • REST APIs
  • WebClient
  • Feign Client
  • Messaging queues (Kafka)

1. RestTemplate (Traditional Approach)

RestTemplate is the older synchronous client provided by Spring.

  • Blocking call
  • Easy to use
  • Suitable for simple applications
  • Officially in maintenance mode (not preferred for new projects)

Dependency

Usually available with Spring Web dependency.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Example

Performing HTTP GET Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public UserDTO getUser(Integer userId) {
        String url = "http://localhost:8081/api/users/{userId}";
        UserDTO userDTO = restTemplate.getForObject(url, UserDTO.class, userId);
    }
}

Performing HTTP POST Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public String addUser(User user) {
        String url = "http://localhost:8081/api/users";
        String response = restTemplate.postForObject(url, user, String.class);
    }
}

Performing HTTP PUT Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public void updateUser(UserDTO userDTO) {
        String url = "http://localhost:8081/api/users/{userId}";
        restTemplate.put(url, UserDTO, UserDTO.getUserId());
    }
}

Performing HTTP DELETE Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public UserDTO deleteUser(Integer userId) {
        String url = "http://localhost:8081/api/users/{userId}";
        restTemplate.delete(url, userId);
    }
}

RestTemplate Bean Configuration

@Configuration
public class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Common Methods

  1. getForObject() -> GET API
  2. postForObject() -> POST API
  3. put() -> PUT API
  4. delete() -> DELETE API
  5. exchange() -> Custom request

Pros

  • Simple and beginner friendly
  • Easy implementation
  • Good for small projects

Cons

  • Blocking/ synchronous
  • Lower performance in high traffic systems
  • Deprecated for modern reactive applications

2. WebClient (Recommended Modern Approach)

Drawbacks of Rest Template:

  • Rest Template is synchronous and blocking, meaning, it waits for the HTTP request to complete before moving on to the next task. This can cause delays because it holds up the execution of other tasks until the current HTTP request finishes.
  • Not suitable for non-blocking environments (for example, WebFlux)

WebClient is introduced in Spring WebFlux.

  • Non-blocking
  • Reactive
  • Better performance
  • Recommended by Spring

Dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

GET API Example

@Service
public class UserService {

    private final WebClient webClient;

    public UserService(WebClient.Builder builder) {
        this.webClient = builder.baseUrl("http://localhost:8081").build();
    }

    public UserDTO getUser() {
        WebClient webClient = WebClient.create();

        return webClient.get()
                .uri("/api/users/{userId}")
                .retrieve()
                .bodyToMono(UserDTO.class)
                .block();
    }
}

Different Ways to Consume REST APIs in Spring Boot Microservices

In Spring Boot, we can integrate external or internal services mainly using:

  • REST APIs
  • WebClient
  • Feign Client
  • Messaging queues (Kafka)

1. RestTemplate (Traditional Approach)

RestTemplate is the older synchronous client provided by Spring.

  • Blocking call
  • Easy to use
  • Suitable for simple applications
  • Officially in maintenance mode (not preferred for new projects)

Dependency

Usually available with Spring Web dependency.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Example

Performing HTTP GET Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public UserDTO getUser(Integer userId) {
        String url = "http://localhost:8081/api/users/{userId}";
        UserDTO userDTO = restTemplate.getForObject(url, UserDTO.class, userId);
    }
}

Performing HTTP POST Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public String addUser(User user) {
        String url = "http://localhost:8081/api/users";
        String response = restTemplate.postForObject(url, user, String.class);
    }
}

Performing HTTP PUT Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public void updateUser(UserDTO userDTO) {
        String url = "http://localhost:8081/api/users/{userId}";
        restTemplate.put(url, UserDTO, UserDTO.getUserId());
    }
}

Performing HTTP DELETE Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public UserDTO deleteUser(Integer userId) {
        String url = "http://localhost:8081/api/users/{userId}";
        restTemplate.delete(url, userId);
    }
}

RestTemplate Bean Configuration

@Configuration
public class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Common Methods

  1. getForObject() -> GET API
  2. postForObject() -> POST API
  3. put() -> PUT API
  4. delete() -> DELETE API
  5. exchange() -> Custom request

Pros

  • Simple and beginner friendly
  • Easy implementation
  • Good for small projects

Cons

  • Blocking/ synchronous
  • Lower performance in high traffic systems
  • Deprecated for modern reactive applications

2. WebClient (Recommended Modern Approach)

Drawbacks of Rest Template:

  • Rest Template is synchronous and blocking, meaning, it waits for the HTTP request to complete before moving on to the next task. This can cause delays because it holds up the execution of other tasks until the current HTTP request finishes.
  • Not suitable for non-blocking environments (for example, WebFlux)

WebClient is introduced in Spring WebFlux.

  • Non-blocking
  • Reactive
  • Better performance
  • Recommended by Spring

Dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

GET API Example

@Service
public class UserService {
    private final WebClient webClient;
    public UserService(WebClient.Builder builder) {
        this.webClient = builder.baseUrl("http://localhost:8081").build();
    }
    public UserDTO getUser() {
        WebClient webClient = WebClient.create();
        return webClient.get()
                .uri("/api/users/{userId}")
                .retrieve()
                .bodyToMono(UserDTO.class)
                .block();
    }
}

POST API Example

public String getUser(User user) {
     WebClient webClient = WebClient.create();
     return webClient.post()
            .uri("/api/users")
            .bodyValue(user)
            .retrieve()
            .bodyToMono(String.class)
            .block();
}

Different Ways to Consume REST APIs in Spring Boot Microservices

In Spring Boot, we can integrate external or internal services mainly using:

  • REST APIs
  • WebClient
  • Feign Client
  • Messaging queues (Kafka)

1. RestTemplate (Traditional Approach)

RestTemplate is the older synchronous client provided by Spring.

  • Blocking call
  • Easy to use
  • Suitable for simple applications
  • Officially in maintenance mode (not preferred for new projects)

Dependency

Usually available with Spring Web dependency.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Example

Performing HTTP GET Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public UserDTO getUser(Integer userId) {
        String url = "http://localhost:8081/api/users/{userId}";
        UserDTO userDTO = restTemplate.getForObject(url, UserDTO.class, userId);
    }
}

Performing HTTP POST Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public String addUser(User user) {
        String url = "http://localhost:8081/api/users";
        String response = restTemplate.postForObject(url, user, String.class);
    }
}

Performing HTTP PUT Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public void updateUser(UserDTO userDTO) {
        String url = "http://localhost:8081/api/users/{userId}";
        restTemplate.put(url, UserDTO, UserDTO.getUserId());
    }
}

Performing HTTP DELETE Request

@Service
public class UserService {
@Autowired
    private RestTemplate restTemplate;
    public UserDTO deleteUser(Integer userId) {
        String url = "http://localhost:8081/api/users/{userId}";
        restTemplate.delete(url, userId);
    }
}

RestTemplate Bean Configuration

@Configuration
public class AppConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Common Methods

  1. getForObject() -> GET API
  2. postForObject() -> POST API
  3. put() -> PUT API
  4. delete() -> DELETE API
  5. exchange() -> Custom request

Pros

  • Simple and beginner friendly
  • Easy implementation
  • Good for small projects

Cons

  • Blocking/ synchronous
  • Lower performance in high traffic systems
  • Deprecated for modern reactive applications

2. WebClient (Recommended Modern Approach)

Drawbacks of Rest Template:

  • Rest Template is synchronous and blocking, meaning, it waits for the HTTP request to complete before moving on to the next task. This can cause delays because it holds up the execution of other tasks until the current HTTP request finishes.
  • Not suitable for non-blocking environments (for example, WebFlux)

WebClient is introduced in Spring WebFlux.

  • Non-blocking
  • Reactive
  • Better performance
  • Recommended by Spring

Dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

GET API Example

@Service
public class UserService {
private final WebClient webClient;
    public UserService(WebClient.Builder builder) {
        this.webClient = builder.baseUrl("http://localhost:8081").build();
    }
    public UserDTO getUser() {
        WebClient webClient = WebClient.create();
        return webClient.get()
                .uri("/api/users/{userId}")
                .retrieve()
                .bodyToMono(UserDTO.class)
                .block();
    }
}

POST API Example

public String getUser(User user) {
     WebClient webClient = WebClient.create();
     return webClient.post()
            .uri("/api/users")
            .bodyValue(user)
            .retrieve()
            .bodyToMono(String.class)
            .block();
}

PUT API Example

public String getUser(UserDTO userDTO) {
     WebClient webClient = WebClient.create();
      return webClient.put()
            .uri("/api/users/{userId}", userDTO.getUserId())
            .bodyValue(user)
            .retrieve();
}

DELETE API Example

public String getUser(Integer userId) {
     WebClient webClient = WebClient.create();

     return webClient.delete()
            .uri("/api/users/{userId}")
            .exchange().subscribe(response -> {
              if(response.statusCode().value() == 200){
                logger.info("User deleted successfully");
              }else {
                logger.info("Failed to delete user");
              }   
            })
            .retrieve()
            .bodyToMono(String.class)
            .block();
}

Pros

  • Non-blocking
  • High performance
  • Reactive support
  • Better resource utilization

Cons

  • Slightly complex
  • Reactive programming learning curve

3. OpenFeign Client (Declarative REST Client)

Feign makes REST API calls very clean and developer friendly.

Instead of writing HTTP client code manually, we define interfaces.

Mostly used in microservices architecture.

Dependency

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

Enable Feign

@SpringBootApplication
@EnableFeignClients
public class Application {
}

Feign Client Example

@FeignClient(name = "user-service", url = "http://localhost:8081")
public interface UserClient {

    @GetMapping("/api/users/1")
    String getUser();
}

Service Layer

@Service
public class UserService {

    @Autowired
    private UserClient userClient;

    public String getUser() {
        return userClient.getUser();
    }
}

Pros

  • Very clean code
  • Less boilerplate
  • Easy integration with Eureka
  • Load balancing support
  • Best for microservices communication

Cons

  • Less control compared to WebClient
  • Mostly synchronous

4. Kafka / Event Driven Communication (Asynchronous)

Sometimes microservices should not communicate directly using REST.

Instead, they communicate asynchronously using Kafka.

Example:

  • Order Service publishes event
  • Payment Service consumes event
  • Notification Service sends email

This improves:

  • Scalability
  • Decoupling
  • Reliability

Kafka Producer Example

@Service
public class KafkaProducerService {

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    public void sendMessage(String message) {
        kafkaTemplate.send("order-topic", message);
    }
}

Kafka Consumer Example

@Service
public class KafkaConsumerService {

    @KafkaListener(topics = "order-topic", groupId = "group-1")
    public void consume(String message) {

        System.out.println("Message received: " + message);
    }
}

Pros

  • Asynchronous communication
  • Highly scalable
  • Better fault tolerance
  • Loose coupling

Cons

  • More setup required
  • Debugging complexity
  • Eventual consistency challenges

Real-Time Industry Usage

Common Enterprise Architecture

  • WebClient → External APIs / reactive systems
  • Feign → Service-to-service communication
  • Kafka → Async event processing

Example:

Order Service
    ↓
Payment Service (Feign)

Order Service
    ↓
Kafka Event
    ↓
Notification Service

Conclusion

Spring Boot provides multiple ways to consume REST APIs:

  • RestTemplate → Simple but old
  • WebClient → Modern and reactive
  • OpenFeign → Best for clean microservice communication
  • Kafka → Best for asynchronous communication

In modern microservices:

  • Prefer Feign for internal communication
  • Prefer WebClient for external APIs/reactive systems
  • Use Kafka for event-driven architecture

메타데이터
post_id
e28c2b6bdf8b
slug
different-ways-to-consume-rest-apis-in-spring-boot-microservices-e28c2b6bdf8b
url
https://medium.com/@vandanavaishnav333/different-ways-to-consume-rest-apis-in-spring-boot-microservices-e28c2b6bdf8b
canonical_url
https://medium.com/@vandanavaishnav333/different-ways-to-consume-rest-apis-in-spring-boot-microservices-e28c2b6bdf8b
author_url
https://medium.com/@vandanavaishnav333
status
ok
fetched_at
2026-06-09 15:37:30