es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Circular reference de Spring Boot Keycloak.

Hola, estoy intentando desarrollar un servicio de Spring Boot. Estoy usando la clase WebMvcConfigurer para crear resolutores de argumentos personalizados. Pero ahora necesito el contexto de seguridad, así que implementé Keycloak. Pero hay una referencia circular entre las clases KeycloakWebSecurityConfigurerAdapter y RequestMappingHandlerAdapter.

Aquí están mis códigos.

@Configuration
public class CommonPredicateConfiguration implements WebMvcConfigurer {

    private RequestMappingHandlerAdapter adapter;

    @Autowired
    public void setAdapter(RequestMappingHandlerAdapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void addArgumentResolvers(List<handlermethodargumentresolver> resolvers) {
        resolvers.add(new CommonPredicateResolver());
    }

    @PostConstruct
    public void prioritizeCommonPredicateMethodHandler() {
        List<handlermethodargumentresolver> argumentResolvers =
                new ArrayList<>(adapter.getArgumentResolvers());
        for (HandlerMethodArgumentResolver resolver : argumentResolvers) {
            if (resolver instanceof QuerydslPredicateArgumentResolver) {
                argumentResolvers.remove(resolver);
                break;
            }
        }
        adapter.setArgumentResolvers(argumentResolvers);
    }
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .anyRequest()
                .permitAll();
        http.csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = new KeycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
}

Se produce un error de referencia circular al compilar el proyecto.

“`text
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘requestMappingHandlerAdapter’ defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Unsatisfied dependency expressed through method ‘requestMappingHandlerAdapter’ parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘mvcContentNegotiationManager’: Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:760) ~[spring-beans-5.3.9.jar:5.3.9]
… 109 common frames omitted
Caused by:

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para resolver el error de referencia circular entre KeycloakWebSecurityConfigurerAdapter y RequestMappingHandlerAdapter, puede mover el objeto RequestMappingHandlerAdapter y el método prioritizeCommonPredicateMethodHandler a la clase KeycloakSecurityConfig desde la clase CommonPredicateConfiguration. Esto funcionará, pero es posible que desee utilizar estos objetos y métodos en una clase personalizada diferente a KeycloakSecurityConfig en el futuro.

    Para hacer esto, una solución es crear una clase de configuración separada para RequestMappingHandlerAdapter y CommonPredicateConfiguration. En esta clase, puede definir un Bean para RequestMappingHandlerAdapter e inyectarlo en CommonPredicateConfiguration usando @Autowired. De esta manera, puede mantener RequestMappingHandlerAdapter y CommonPredicateConfiguration separados de la clase KeycloakSecurityConfig.

    Aquí hay un ejemplo de cómo podría hacerlo:

    @Configuration
    public class CustomWebMvcConfig {
    
        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            return new RequestMappingHandlerAdapter();
        }
    
        @Configuration
        public static class CustomArgumentResolverConfiguration extends WebMvcConfigurerAdapter {
    
            private final RequestMappingHandlerAdapter adapter;
    
            @Autowired
            public CustomArgumentResolverConfiguration(RequestMappingHandlerAdapter adapter) {
                this.adapter = adapter;
            }
    
            @Override
            public void addArgumentResolvers(List<handlermethodargumentresolver> resolvers) {
                resolvers.add(new CommonPredicateResolver());
            }
    
            @PostConstruct
            public void prioritizeCommonPredicateMethodHandler() {
                List<handlermethodargumentresolver> argumentResolvers =
                        new ArrayList<>(adapter.getArgumentResolvers());
                for (HandlerMethodArgumentResolver resolver : argumentResolvers) {
                    if (resolver instanceof QuerydslPredicateArgumentResolver) {
                        argumentResolvers.remove(resolver);
                        break;
                    }
                }
                adapter.setArgumentResolvers(argumentResolvers);
            }
    
        }
    }
    

    Ahora puede inyectar CommonPredicateConfiguration en su clase KeycloakSecurityConfig y debería funcionar sin errores de referencia circular.

    “`java
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(jsr250Enabled = true)
    public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    private final CommonPredicateConfiguration commonPredicateConfiguration;
    
    public KeycloakSecurityConfig(CommonPredicateConfiguration commonPredicateConfiguration) {
        this.commonPredicateConfiguration = commonPredicateConfiguration;
    }
    
    // Resto de su configuración ...
    

    }
    “`

Comments are closed.