During certain checks, I need to make a request to my Microservice in the Gateway Filter. When I define the Feign class in the GatewayFilter(my SecurityFilter.java) class, it gives the following error. How can I resolve this situation.
Error:
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityFilter defined in file [/target/classes/com/example/SecurityFilter.class]
↑ ↓
| cachedCompositeRouteLocator defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]
↑ ↓
| routeDefinitionRouteLocator defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]
└─────┘
Action:
Despite circular references being allowed, the dependency cycle between beans could not be broken. Update your application to remove the dependency cycle.
GatewayFilter class
@Component
public class SecurityFilter implements GatewayFilterFactory<SecurityFilter.Config> {
private final UserApi userApi;
public SecurityFilter(UserApi userApi) {
this.userApi = userApi;
}
@Override
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
});
}
@Override
public Class<Config> getConfigClass() {
return Config.class;
}
@Override
public Config newConfig() {
Config c = new Config();
return c;
}
public static class Config {
}
}
pom.xml
<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</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>
Main class
@SpringBootApplication
@ComponentScan("com.example")
@EnableFeignClients(basePackages = {"com.example.feign"})
public class GatewayApplicationMain {
public static void main(String[] args) {
SpringApplication.run(GatewayApplicationMain.class, args);
}
}
Feign api class
@FeignClient(name = "user", path="userService/", url="http://localhost:8091/")
public interface UserApi {
@GetMapping("/getUserByUserName/{userName}")
ResponseEntity<Object> getUserByUserName(@PathVariable(name = "userName") String userName);
}
Security class
@Configuration
public class SecurityConfig {
@Bean
public SecurityWebFilterChain configure(ServerHttpSecurity http) {
http.csrf().disable()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2Login()
.and().oauth2ResourceServer().jwt();
return http.build();
}
}
application.properties file
server.port=8090
spring.main.allow-circular-references=true
private final UserApi userApi;
@Autowired
public SecurityFilter(@Lazy UserApi userApi) {
this.userApi = userApi;
}
This is how I was able to fix the problem by adding @Lazy.