Service Discovery and Inter-Service Communication in Spring Cloud with Eureka

Using Netflix Feign Client for Service Calls

First, add the spring-cloud-starter-openfeign dependency to your project:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <artifactId>service-consumer</artifactId>
    <name>service-consumer</name>
    <description>Service consumer application</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>shared-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!-- Spring Boot dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Cloud dependencies -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- Other dependencies -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Next, define a FeignClient interfacce for the service you want to call. Note that you must specify the service name in the value attribute:

package com.example.client.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.shared.model.ApiResponse;

@FeignClient(value = "service-provider")
@RequestMapping("/api/service")
public interface ProviderServiceClient {

    @GetMapping("/details")
    ApiResponse<String> getServiceDetails();
}

Implement the service endpoint:

package com.example.provider.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import com.example.shared.model.ApiResponse;
import com.example.client.feign.ProviderServiceClient;

@RestController
public class ProviderController implements ProviderServiceClient {
    @Override
    public ApiResponse<String> getServiceDetails() {
        ApiResponse<String> response = new ApiResponse<>();
        response.setStatus(String.valueOf(HttpStatus.OK.value()));
        response.setMessage(HttpStatus.OK.getReasonPhrase());
        response.setData("Service Provider Details");
        return response;
    }
}

For the API module, include the Feign dependency:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <artifactId>shared-api</artifactId>
    <name>shared-api</name>
    <description>Shared API models</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <!-- Spring Cloud Feign dependency -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- Other dependencies -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

In the consumer application's main class, enable Feign clients and specify the packages to scan:

package com.example.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.client.feign.ProviderServiceClient;
import com.example.shared.model.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients({"com.example.client.feign"})
@RestController
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    @Autowired
    private ProviderServiceClient providerServiceClient;

    @GetMapping("/call-service")
    public ApiResponse<String> callService() {
        return providerServiceClient.getServiceDetails();
    }
}

Using RestTemplate with Ribbon for Service Calls

Create a RestTemplate bean with the @LoadBalanced annotation to anable Ribbon load balancing:

@LoadBalanced
@Bean
public RestTemplate loadBalancedRestTemplate() {
    return new RestTemplate();
}

Use the load-balanced RestTemplate to call services:

@GetMapping("/ribbon-call")
public ApiResponse<String> ribbonCall() {
    ResponseEntity<ApiResponse> response = restTemplate.exchange(
            "http://service-provider/api/service/details",
            HttpMethod.GET, null, ApiResponse.class);
    return response.getBody();
}

Using DiscoveryClient with Standard RestTemplate

Use DiscoveryClient to locate service insatnces and then call them with a standard RestTemplate:

@Autowired
private DiscoveryClient discoveryClient;

@GetMapping("/discovery-call")
public ApiResponse<String> discoveryCall() {
    List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
    if (instances.isEmpty()) {
        ApiResponse<String> errorResponse = new ApiResponse<>();
        errorResponse.setStatus("404");
        errorResponse.setMessage("Service not found");
        return errorResponse;
    } else {
        ServiceInstance instance = instances.get(0);
        String serviceUrl = instance.getUri().toString();
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<ApiResponse> response = restTemplate.exchange(
                serviceUrl + "/api/service/details",
                HttpMethod.GET, null, ApiResponse.class);
        return response.getBody();
    }
}

Tags: spring-cloud Eureka feign rest-template service-discovery

Posted on Mon, 11 May 2026 13:30:21 +0000 by thoand