2121import java .util .concurrent .TimeUnit ;
2222import java .util .concurrent .locks .Lock ;
2323import java .util .concurrent .locks .ReentrantLock ;
24+ import java .util .function .Supplier ;
25+
26+ import org .jspecify .annotations .Nullable ;
2427
2528import org .springframework .beans .factory .DisposableBean ;
2629import org .springframework .context .ApplicationEventPublisher ;
5962 *
6063 * @since 4.3.1
6164 */
62- public class LockRegistryLeaderInitiator implements SmartLifecycle , DisposableBean ,
63- ApplicationEventPublisherAware {
65+ public class LockRegistryLeaderInitiator implements SmartLifecycle , DisposableBean , ApplicationEventPublisherAware {
6466
6567 public static final long DEFAULT_HEART_BEAT_TIME = 500L ;
6668
@@ -115,14 +117,15 @@ public String getRole() {
115117
116118 private boolean publishFailedEvents = false ;
117119
118- private LeaderSelector leaderSelector ;
120+ private @ Nullable LeaderSelector leaderSelector ;
119121
122+ @ SuppressWarnings ("NullAway.Init" )
120123 private ApplicationEventPublisher applicationEventPublisher ;
121124
122125 /**
123126 * Leader event publisher if set.
124127 */
125- private LeaderEventPublisher leaderEventPublisher ;
128+ private @ Nullable LeaderEventPublisher leaderEventPublisher ;
126129
127130 /**
128131 * @see SmartLifecycle
@@ -132,7 +135,7 @@ public String getRole() {
132135 /**
133136 * @see SmartLifecycle which is an extension of org.springframework.context.Phased
134137 */
135- private int phase = Integer .MAX_VALUE - 1000 ; // NOSONAR magic number
138+ private int phase = Integer .MAX_VALUE - 1000 ;
136139
137140 /**
138141 * Time in milliseconds to wait in between attempts to acquire the lock, if it is not
@@ -155,7 +158,7 @@ public String getRole() {
155158 * Future returned by submitting an {@link LeaderSelector} to
156159 * {@link #taskExecutor}. This is used to cancel leadership.
157160 */
158- private volatile Future <?> future ;
161+ private volatile @ Nullable Future <?> future ;
159162
160163 /**
161164 * Create a new leader initiator with the provided lock registry and a default
@@ -279,7 +282,7 @@ public void setPublishFailedEvents(boolean publishFailedEvents) {
279282 public void start () {
280283 this .lock .lock ();
281284 try {
282- if (this .leaderEventPublisher == null && this . applicationEventPublisher != null ) {
285+ if (this .leaderEventPublisher == null ) {
283286 this .leaderEventPublisher = new DefaultLeaderEventPublisher (this .applicationEventPublisher );
284287 }
285288 if (!this .running ) {
@@ -309,8 +312,9 @@ public void stop() {
309312 try {
310313 if (this .running ) {
311314 this .running = false ;
312- if (this .future != null ) {
313- this .future .cancel (true );
315+ Future <?> futureToCancel = this .future ;
316+ if (futureToCancel != null ) {
317+ futureToCancel .cancel (true );
314318 }
315319 this .future = null ;
316320 LOGGER .debug (() -> "Stopped LeaderInitiator for " + getContext ());
@@ -334,7 +338,7 @@ protected class LeaderSelector implements Callable<Void> {
334338
335339 private final String lockKey ;
336340
337- private final LockContext context = new LockContext ();
341+ private final LockContext context = new LockContext (this );
338342
339343 private volatile boolean locked = false ;
340344
@@ -421,7 +425,7 @@ else if (acquired) {
421425 }
422426 }
423427
424- private boolean unlockAndHandleException (Exception ex ) { // NOSONAR
428+ private boolean unlockAndHandleException (@ Nullable Exception ex ) {
425429 if (this .locked ) {
426430 this .locked = false ;
427431 try {
@@ -450,18 +454,31 @@ private boolean unlockAndHandleException(Exception ex) { // NOSONAR
450454 Thread .sleep (LockRegistryLeaderInitiator .this .busyWaitMillis );
451455 }
452456 catch (InterruptedException e1 ) {
453- // Ignore interruption and let it be caught on the next cycle.
457+ // Ignore the interruption and let it be caught on the next cycle.
454458 Thread .currentThread ().interrupt ();
455459 }
456460 }
457- LOGGER .debug (ex , () ->
458- "Error acquiring the lock for " + this .context + ". " + (isRunning () ? "Retrying..." : "" ));
461+ Supplier <CharSequence > debugMessage =
462+ () -> "Error acquiring the lock for " + this .context + ". " + (isRunning () ? "Retrying..." : "" );
463+ if (ex != null ) {
464+ LOGGER .debug (ex , debugMessage );
465+ }
466+ else {
467+ LOGGER .debug (debugMessage );
468+ }
459469 }
460470 return false ;
461471 }
462472
463- private void restartSelectorBecauseOfError (Exception ex ) {
464- LOGGER .warn (ex , () -> "Restarting LeaderSelector for " + this .context + " because of error." );
473+ private void restartSelectorBecauseOfError (@ Nullable Exception ex ) {
474+ Supplier <CharSequence > warnMessage =
475+ () -> "Restarting LeaderSelector for " + this .context + " because of error." ;
476+ if (ex != null ) {
477+ LOGGER .warn (ex , warnMessage );
478+ }
479+ else {
480+ LOGGER .warn (warnMessage );
481+ }
465482 LockRegistryLeaderInitiator .this .future =
466483 LockRegistryLeaderInitiator .this .taskExecutor .submit (
467484 () -> {
@@ -523,18 +540,21 @@ private void publishFailedToAcquire() {
523540 */
524541 private class LockContext implements Context {
525542
526- LockContext () {
543+ private final LeaderSelector selector ;
544+
545+ LockContext (LeaderSelector leaderSelector ) {
546+ this .selector = leaderSelector ;
527547 }
528548
529549 @ Override
530550 public boolean isLeader () {
531- return LockRegistryLeaderInitiator . this .leaderSelector .isLeader ();
551+ return this .selector .isLeader ();
532552 }
533553
534554 @ Override
535555 public void yield () {
536556 LOGGER .debug (() -> "Yielding leadership from " + this );
537- LockRegistryLeaderInitiator . this .leaderSelector .yielding = true ;
557+ this .selector .yielding = true ;
538558 }
539559
540560 @ Override
0 commit comments