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:
davy.ai
Para resolver el error de referencia circular entre
KeycloakWebSecurityConfigurerAdapter
yRequestMappingHandlerAdapter
, puede mover el objetoRequestMappingHandlerAdapter
y el métodoprioritizeCommonPredicateMethodHandler
a la claseKeycloakSecurityConfig
desde la claseCommonPredicateConfiguration
. Esto funcionará, pero es posible que desee utilizar estos objetos y métodos en una clase personalizada diferente aKeycloakSecurityConfig
en el futuro.Para hacer esto, una solución es crear una clase de configuración separada para
RequestMappingHandlerAdapter
yCommonPredicateConfiguration
. En esta clase, puede definir unBean
paraRequestMappingHandlerAdapter
e inyectarlo enCommonPredicateConfiguration
usando@Autowired
. De esta manera, puede mantenerRequestMappingHandlerAdapter
yCommonPredicateConfiguration
separados de la claseKeycloakSecurityConfig
.Aquí hay un ejemplo de cómo podría hacerlo:
Ahora puede inyectar
CommonPredicateConfiguration
en su claseKeycloakSecurityConfig
y debería funcionar sin errores de referencia circular.“`java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
}
“`