Home > Net >  The dependencies of some of the beans in the application context form a cycle @RequiredArgsConstruct
The dependencies of some of the beans in the application context form a cycle @RequiredArgsConstruct

Time:10-06

In my Config class I have bean with RestTemplate and I had to add CurrencyConverterService currencyConverter becoues I am using it in modelMapper. Config class:

@Configuration
@RequiredArgsConstructor
public class Config {
    private final CurrencyConverterService currencyConverter;

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@Bean
public ModelMapper modelMapper() {
    ModelMapper modelMapper = new ModelMapper();
... }

but in currencyConverter I have to use RestTemplate to get current currency rates from api so I added RestTemplate:

@Service
@RequiredArgsConstructor
public class CurrencyConverterService {
    private static String BASE_URL = url...;
    private final RestTemplate restTemplate;
    private final CurrencyEntityRepository currencyEntityRepository;

and of course I am getting error:

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  config defined in file [C:\config\Config.class]
↑     ↓
|  currencyConverterService defined in file [C\service\CurrencyConverterService.class]
└─────┘

I was trying to add @Lazy up to restTemplate in CurrencyService but it does not help.

spring.main.allow-circular-references= true did not help too

CodePudding user response:

What about

@Configuration
public class Config {
 
  @Bean
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

  @Bean
  public ModelMapper modelMapper(final CurrencyConverterService currencyConverter) {
    ModelMapper modelMapper = new ModelMapper();
    ...
  }
  ...
}

when you create a bean you can pass other beans as parameter

CodePudding user response:

Solution 1: use javax.inject.Provider

Assuming you are using Maven you can add the following dependency:

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>

And then in CurrencyConverterService inject an instance of javax.inject.Provider of RestTemplate:

import javax.inject.Provider;
...
@Service
@RequiredArgsConstructor
public class CurrencyConverterService {
    ...
    private final Provider<RestTemplate> restTemplate;

And retrieve the instance with restTemplate.get().

However this will still fail during runtime in case of circular usage.

Solution 2: resolve cyclic dependency

Assuming you do not need the CurrencyConverterService for constructing RestTemplate the more stable solution is to create a second class producing the RestTemaplate (you can have as many classes annotated with @Configuration or @Component as you want):

@Configuration
public class RestTemplateProducer {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}
  • Related