Dispose default Scheduler
AbstractUserDetailsReactiveAuthenticationManager creates parallel Scheduler with daemon=false Threads. It is recommended to dispose such Schedulers to be able exit the VM Fixes gh-7492
This commit is contained in:
		
							parent
							
								
									29ed728a70
								
							
						
					
					
						commit
						39600b901f
					
				| 
						 | 
				
			
			@ -18,6 +18,7 @@ package org.springframework.security.authentication;
 | 
			
		|||
 | 
			
		||||
import org.apache.commons.logging.Log;
 | 
			
		||||
import org.apache.commons.logging.LogFactory;
 | 
			
		||||
import org.springframework.beans.factory.DisposableBean;
 | 
			
		||||
import reactor.core.publisher.Mono;
 | 
			
		||||
import reactor.core.scheduler.Scheduler;
 | 
			
		||||
import reactor.core.scheduler.Schedulers;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +46,7 @@ import org.springframework.util.Assert;
 | 
			
		|||
 * @author Eddú Meléndez
 | 
			
		||||
 * @since 5.2
 | 
			
		||||
 */
 | 
			
		||||
public abstract class AbstractUserDetailsReactiveAuthenticationManager implements ReactiveAuthenticationManager {
 | 
			
		||||
public abstract class AbstractUserDetailsReactiveAuthenticationManager implements ReactiveAuthenticationManager, DisposableBean {
 | 
			
		||||
 | 
			
		||||
	protected final Log logger = LogFactory.getLog(getClass());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +56,8 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement
 | 
			
		|||
 | 
			
		||||
	private ReactiveUserDetailsPasswordService userDetailsPasswordService;
 | 
			
		||||
 | 
			
		||||
	private Scheduler scheduler = Schedulers.newParallel("password-encoder");
 | 
			
		||||
	Scheduler scheduler = Schedulers.newParallel("password-encoder");
 | 
			
		||||
	private boolean defaultScheduler = true;
 | 
			
		||||
 | 
			
		||||
	private UserDetailsChecker preAuthenticationChecks = user -> {
 | 
			
		||||
		if (!user.isAccountNonLocked()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,6 +140,10 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement
 | 
			
		|||
	 */
 | 
			
		||||
	public void setScheduler(Scheduler scheduler) {
 | 
			
		||||
		Assert.notNull(scheduler, "scheduler cannot be null");
 | 
			
		||||
		if (this.defaultScheduler) {
 | 
			
		||||
			this.defaultScheduler = false;
 | 
			
		||||
			this.scheduler.dispose();
 | 
			
		||||
		}
 | 
			
		||||
		this.scheduler = scheduler;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -171,4 +177,10 @@ public abstract class AbstractUserDetailsReactiveAuthenticationManager implement
 | 
			
		|||
	 */
 | 
			
		||||
	protected abstract Mono<UserDetails> retrieveUser(String username);
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void destroy() {
 | 
			
		||||
		if (this.defaultScheduler) {
 | 
			
		||||
			this.scheduler.dispose();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,8 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
 | 
			
		|||
import org.springframework.security.core.userdetails.UserDetails;
 | 
			
		||||
import org.springframework.security.crypto.password.PasswordEncoder;
 | 
			
		||||
import reactor.core.publisher.Mono;
 | 
			
		||||
import reactor.core.scheduler.Scheduler;
 | 
			
		||||
import reactor.core.scheduler.Schedulers;
 | 
			
		||||
import reactor.test.StepVerifier;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -136,4 +138,33 @@ public class ReactiveUserDetailsServiceAuthenticationManagerTests {
 | 
			
		|||
			.expectError(BadCredentialsException.class)
 | 
			
		||||
			.verify();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void destroyWhenDefaultSchedulerThenShouldDispose() {
 | 
			
		||||
		assertThat(manager.scheduler.isDisposed()).isFalse();
 | 
			
		||||
		manager.destroy();
 | 
			
		||||
		assertThat(manager.scheduler.isDisposed())
 | 
			
		||||
				.as("default Scheduler should be disposed")
 | 
			
		||||
				.isTrue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void destroyWhenCustomSchedulerThenShouldNotDispose() {
 | 
			
		||||
		manager.setScheduler(Schedulers.parallel());
 | 
			
		||||
		manager.destroy();
 | 
			
		||||
		assertThat(manager.scheduler.isDisposed())
 | 
			
		||||
				.as("custom Scheduler should not be disposed")
 | 
			
		||||
				.isFalse();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void setSchedulerWhenSetCustomSchedulerThenDisposeDefault() {
 | 
			
		||||
		Scheduler defaultScheduler = manager.scheduler;
 | 
			
		||||
		assertThat(defaultScheduler.isDisposed()).isFalse();
 | 
			
		||||
		manager.setScheduler(Schedulers.parallel());
 | 
			
		||||
		assertThat(defaultScheduler.isDisposed())
 | 
			
		||||
				.as("default Scheduler should be disposed")
 | 
			
		||||
				.isTrue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue