While migrating to the new Spring Boot 3.4 version I am facing the following error in a project with RSocket, Spring Security and Spring Webflux:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method setAuthenticationManagerPostProcessor in org.springframework.security.config.annotation.web.reactive.ServerHttpSecurityConfiguration required a single bean, but 2 were found:
    - authenticationManagerPostProcessor: defined by method 'authenticationManagerPostProcessor' in class path resource [org/springframework/security/config/annotation/web/reactive/ReactiveObservationConfiguration.class]
    - rSocketAuthenticationManagerPostProcessor: defined by method 'rSocketAuthenticationManagerPostProcessor' in class path resource [org/springframework/security/config/annotation/rsocket/ReactiveObservationConfiguration.class]

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

I was able to reproduce this in a simple project which you can find at https://github.com/joaodias14/Spring-Boot-RSocket. I simply used https://start.spring.io/ with Spring Boot 3.4.0 and RSocket, Spring Reactive Web and Spring Security as dependencies. If I run it with ./mvnw -o spring-boot:run I get the error above.

Comment From: jzheaux

Thanks for the report, @joaodias14. I'm able to reproduce this issue; we'll get a fix out in the next maintenance release.

In the meantime, if you are not using Security's Observability integration, then you can do:

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Primary
static ObjectPostProcessor<ReactiveAuthorizationManager<ServerWebExchange>> primaryAuthorizationManagerPostProcessor() {
    return ObjectPostProcessor.identity();
}

@Bean
@Role(2)
@Primary
static ObjectPostProcessor<ReactiveAuthenticationManager> primaryAuthenticationManagerPostProcessor() {
    return ObjectPostProcessor.identity();
}

@Bean
@Role(2)
@Primary
static ObjectPostProcessor<WebFilterChainProxy.WebFilterChainDecorator> primaryFilterChainDecoratorPostProcessor() {
    return ObjectPostProcessor.identity();
}

Or, if you are, then you can instead do:

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Primary
static ObjectPostProcessor<ReactiveAuthorizationManager<ServerWebExchange>> primaryAuthorizationManagerPostProcessor(
    ObjectProvider<ObservationRegistry> registry) {
    return new ObjectPostProcessor<>() {
        @Override
        public ReactiveAuthorizationManager postProcess(ReactiveAuthorizationManager object) {
            ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
            return new ObservationReactiveAuthorizationManager<>(r, object);
        }
    };
}

@Bean
@Role(2)
@Primary
static ObjectPostProcessor<ReactiveAuthenticationManager> primaryAuthenticationManagerPostProcessor(ObjectProvider<ObservationRegistry> registry) {
    return new ObjectPostProcessor<>() {
        public ReactiveAuthenticationManager postProcess(ReactiveAuthenticationManager object) {
            ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
            return new ObservationReactiveAuthenticationManager(r, object);
        }
    };
}

@Bean
@Role(2)
@Primary
static ObjectPostProcessor<WebFilterChainProxy.WebFilterChainDecorator> primaryFilterChainDecoratorPostProcessor(ObjectProvider<ObservationRegistry> registry) {
    return new ObjectPostProcessor<>() {
        public WebFilterChainProxy.WebFilterChainDecorator postProcess(WebFilterChainProxy.WebFilterChainDecorator object) {
            ObservationRegistry r = registry.getIfUnique(() -> ObservationRegistry.NOOP);
            return new ObservationWebFilterChainDecorator(r);
        }
    };
}

Comment From: ngocnhan-tran1996

@jzheaux

We will add @Primary or have another handle way when both RSocket and Webflux are on classpath?

Comment From: joaodias14

Many thanks for the quick workaround @jzheaux !

Comment From: jzheaux

Good question, @ngocnhan-tran1996, please see the commit for details; it disambiguates in the setter to preserve Spring Security's getIfUnique semantics.