Search code examples
javaspring-bootmavennetflix-eurekaspring-cloud-gateway

Spring Cloud Gateway with Eureka Discovery not routing requests to Microservices


I'm working on a project with multiple microservices registered with a Eureka Discovery Server. I've set up a Spring Cloud Gateway as an Eureka client and configured the routes accordingly. However, my requests through the Gateway result in 404 errors, while direct requests to the microservices succeed.

API Gateway application.properties:

eureka.client.service-url.defaultZone= http://localhost:8761/eureka/
spring.application.name=api-gateway
server.port=8080

##Product Service Route
spring.cloud.gateway.routes[0].id=product-service
spring.cloud.gateway.routes[0].uri=lb://product-service
spring.cloud.gateway.routes[0].predicates[0]=Path=/api/product

##Order Service Route
spring.cloud.gateway.routes[1].id=order-service
spring.cloud.gateway.routes[1].uri=lb://order-service
spring.cloud.gateway.routes[1].predicates[0]=Path=/api/order

ApiGatewayMain:


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {

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

pom.xml:

<artifactId>api-gateway</artifactId>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>2023.0.0</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway-mvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </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>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

Both my microservices (order-service and product-service) have server.port=0 for random port selection and are registered with Eureka:

order-service and product-service application.properties:

eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
spring.application.name=order-service  # for order-service
# spring.application.name=product-service  # for product-service

OrderController:

@RestController
@RequestMapping("/api/order")
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public String placeOrder(@RequestBody OrderRequest orderRequest) {
        orderService.placeOrder(orderRequest);
        return "Order placed successfully";
    }
    // ... other methods ...
}

ProductController:

@RestController
@RequestMapping("/api/product")
@RequiredArgsConstructor
public class ProductController {
    private final ProductService productService;
    // ... methods ...
}

Issue:

When making a POST request to http://localhost:8080/api/order via Postman, I receive the following error:

{
    "timestamp": "2024-03-08T20:08:59.340+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/api/order"
}

However, directly calling the order-service using its dynamically assigned port, such as http://localhost:54062/api/order, works correctly and I receive a Order placed successfully response.

What am I missing in my Gateway setup that's preventing it from routing requests to the microservices? Any insights or troubleshooting tips would be greatly appreciated.


Solution

  • Please use

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

    instead of

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