Problem : I have 2 functional endpoints

@Bean
public RouterFunction<ServerResponse> getById() {
    return RouterFunctions.route(
            GET("/threads/{threadId}"),
            request -> ServerResponse.ok().bodyValue("/threads/{threadId}")
    );
}
@Bean
public RouterFunction<ServerResponse> getSomeEntity() {
    return RouterFunctions.route(
            GET("/threads/some"),
            request -> ServerResponse.ok().bodyValue("/threads/some"));
}

When i make request with GET /threads/some

Expected behavior : handler from getSomeEntity router function bean will be invoked, response (/threads/some) Actual behavior : handler from getById router function bean will be invoked, response (/threads/{threadId})

so it is impossible to invoke handler function from getSomeEntity() bean, because always invokes getById.

also tried to unite this 2 functions into one RouterFunction bean, problem also reproduces

NOTE if try to model same situation with @RestController and @GetMapping pattern matching works as expected

spring boot version: 2.3.5 Release

from dependencies only

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





**Comment From: philwebb**

I don't think that `RouterFunction` beans work in the same way as `@RestController` mappings. I think the first matching route will win. You could try adding `@Order` to your bean definitions so that the `/threads/some` function is before the pattern.

I'll transfer this issue to the Spring Framework team that are responsible for this code.

**Comment From: tka4ukalex**

Thank you, as temporary workaround @Order helped

**Comment From: bclozel**

As Phil said, routes defined within a `RouterFunction` [will be evaluated in order](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-fn-routes).

This means that if you define both `GET("/threads/{threadId}")` and `GET("/threads/some")` in the same `RouterFunction`, `GET("/threads/some")` should be defined first as it's the most specific. This is an important design principle with WebFlux.fn.

I'm not sure if the code snippet you've provided is a sample repro or is an actual part of your application. In most cases, you should try and declare related routes (or all your app routes, it's your call) within the same `RouterFunction`. Something like this:

@Bean public RouterFunction getById() { return RouterFunctions.route() .GET("/threads/some", request -> ServerResponse.ok().bodyValue("/threads/some")) .GET("/threads/{threadId}", request -> ServerResponse.ok().bodyValue("/threads/{threadId}")) .build(); ); } ```

This, as well as nested routes, is explained in the reference docs.

You can define multiple RouterFunction instances in your application. Maybe you want to have one per "feature slice" in your application and keep handlers and routes package private. In this case, related routes should still be defined in the same RouterFunction. During startup, all RouterFunction components are loaded and reduced, in order, as a single RouterFunction.

To summarize, ordering between routes is guaranteed by:

  • their declaration order within a RouterFunction
  • the RouterFunction ordering of components, using the standard Spring ordering mechanism with @Order or implements Ordered.

In your case, declaring related routes within the same RouterFunction seems like a good match. If there are other constraints not shown in your sample, then @Order is not a workaround, but the expected way of achieving this.

I'm leaving this issue opened for now as this specific part might not be well documented in the reference docs. Paging @poutsma for an opinion here.

Comment From: tka4ukalex

@bclozel thank you for your detailed explanation, now everything is clear.