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());
}
}
Here is my solution
public UserServiceImpl(UserMapper userMapper,UserRepository userRepository,@Lazy PasswordEncoder passwordEncoder) {
super();
this.userMapper = userMapper;
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
Try using @Lazy
public class WebSecurity extends WebSecurityConfigurerAdapter {
private Environment environment;
@Lazy
private UserService userService;
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
?
If you declare the bean factory method for the password encoder static
, ie
@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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.