Spring circular references prohibited in 2.6 version

151
June 12, 2022, at 08:40 AM

I have an issue for circular reference calling. Even if I set true to this option, I cannot fix my issue. How can I fix it? Here are my code snippets which are shown below step by step.

Here is my application.properties file shown below.

...
spring.main.allow-circular-references= true
...

Here is my error message shown below.

Description:
The dependencies of some of the beans in the application context form a cycle:
   userController (field com.photoapp.users.service.UserService com.photoapp.users.controller.UserController.userService)
┌─────┐
|  userServiceImpl defined in file [C:\Users\de\Desktop\sts-4.9.0.RELEASE\workspace\PhotoAppApiUsers\target\classes\com\photoapp\users\service\impl\UserServiceImpl.class]
↑     ↓
|  webSecurity defined in file [C:\Users\de\Desktop\sts-4.9.0.RELEASE\workspace\PhotoAppApiUsers\target\classes\com\photoapp\users\security\WebSecurity.class]
└─────┘

Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

Here is my userServiceImpl class

@Service
@Transactional
public class UserServiceImpl implements UserService{
    UserMapper userMapper;
    
    UserRepository userRepository;
    
    PasswordEncoder passwordEncoder;
    
    @Autowired
    public UserServiceImpl(UserMapper userMapper,UserRepository userRepository,PasswordEncoder passwordEncoder) {
        super();
        this.userMapper = userMapper;
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public UserDto createUser(UserDto userDetails) {
        // TODO Auto-generated method stub
        
        userDetails.setUserId(UUID.randomUUID().toString());
        
        User user = userMapper.userDtotoUser(userDetails);
        
        
        String encodedPassword = passwordEncoder.encode(userDetails.getPassword());
        user.setEncryptedPassword(encodedPassword);
        
        userRepository.save(user);
        
        UserDto returnValue = userMapper.userToUserDto(user);
 
        return returnValue;
        
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // TODO Auto-generated method stub
        User user = userRepository.findByEmail(username);
        
        if(user == null) 
            throw new UsernameNotFoundException(username);  
        
        return new org.springframework.security.core.userdetails.User(user.getEmail(), 
                user.getEncryptedPassword(), 
                true, true, true, true, new ArrayList<>());
    }
    
    @Override
    public UserDto getUserDetailsByEmail(String email) { 
        User user = userRepository.findByEmail(email);
        
        if(user == null) 
            throw new UsernameNotFoundException(email);
        
        UserDto returnValue = userMapper.userToUserDto(user);
        
        return returnValue;
    }

    @Override
    public UserDto getUserByUserId(String userId) {
        // TODO Auto-generated method stub
        return null;
    }
}

Here is my WebSecurity class

@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
    
    private Environment environment;
    private UserService userService;
    
    @Autowired
    public WebSecurity(Environment environment, UserService userService) {
        super();
        this.environment = environment;
        this.userService = userService;
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // TODO Auto-generated method stub
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/users").hasIpAddress(environment.getProperty("gateway.ip"))
        .and()
        .addFilter(getAuthenticationFilter());
        http.headers().frameOptions().disable();
    }
    private AuthenticationFilter getAuthenticationFilter() throws Exception{
        AuthenticationFilter authenticationFilter = new AuthenticationFilter(userService, environment, authenticationManager());
        //authenticationFilter.setAuthenticationManager(authenticationManager()); 
        authenticationFilter.setFilterProcessesUrl(environment.getProperty("login.url.path"));
        return authenticationFilter;
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
}
Answer 1

Here is my solution

public UserServiceImpl(UserMapper userMapper,UserRepository userRepository,@Lazy PasswordEncoder passwordEncoder) {
        super();
        this.userMapper = userMapper;
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }
Answer 2

Try using @Lazy

public class WebSecurity extends WebSecurityConfigurerAdapter {
    
    private Environment environment;
    @Lazy
    private UserService userService;

Reference: https://www.baeldung.com/spring-lazy-annotation

Answer 3

The error message is pretty clear. UserServiceImpl depends on WebSecurity which depends on UserServiceImpl.

The dependency from WebSecurity to UserServiceImpl is necessary. That means you need to break the dependency from UserServiceImpl to WebSecurity. This is caused by the password encoder. You need to move that out of WebSecurity. Maybe you can integrate it in UserServiceImpl?

Answer 4

If you declare the bean factory method for the password encoder static, i.e.

@Bean
public static PasswordEncoder passwordEncoder() {
  return new BCryptPasswordEncoder();
}

you make it clear that the bean does not actually depend on anything that is injected into WebSecurity. Then, you don't need to work with @Lazy and the proxying it creates.

You may even be able to remove the property that allows circular references. But that depends on the whole rest of your application.

Rent Charter Buses Company
READ ALSO
org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]

org.apache.hadoop.security.AccessControlException: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]

I am trying to execute the hive table query in presto using Kerberos authentication, But it failed

183
Spring boot gradle build failing due to exception &quot;HikariPool$PoolInitializationException&quot; in unit test

Spring boot gradle build failing due to exception "HikariPool$PoolInitializationException" in unit test

Test cases are running fine when we run them individually it only gives this exception when we are trying to create a build

107
How is XOR helping find the unique value?

How is XOR helping find the unique value?

I have a problem to writhe a function that finds the unique value from an array, i could not solve the problem but i asked someone to help, he provided the solution by using XOR(^), but could not explain for me to understand itI know that XOR has the following...

117