From ac146266d63fce09b16f9073607755e33d550146 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 13 Sep 2026 23:17:19 +0200 Subject: [PATCH] bug6288: replace Consumer[] holder with generic Holder The confirm-and-force retry in LandscapeManagementPanel needs each issueRequest lambda to reference itself, which previously forced a one-element Consumer[] array holder plus @SuppressWarnings("unchecked"). Introduce com.sap.sse.common.util.Holder (mirroring IntHolder/ DoubleHolder, GWT/Android/OSGi-safe) and use it at all five sites, removing the array idiom and the unchecked-cast suppressions. No behavioral change: each AsyncCallback is still constructed inside the lambda body, so a fresh callback is created per (initial and forced) invocation. Also carry over the CLAUDE.md note about keeping auto-formatting scoped to the actual change. Assisted-By: Claude Opus 4.8 (claude-opus-5) --- CLAUDE.md | 2 + .../ui/client/LandscapeManagementPanel.java | 46 +++++++++---------- .../src/com/sap/sse/common/util/Holder.java | 21 +++++++++ 3 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 java/com.sap.sse.common/src/com/sap/sse/common/util/Holder.java diff --git a/CLAUDE.md b/CLAUDE.md index 894f74d2be8..9e1754af687 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,6 +10,8 @@ Make sure to research the topic/question well and thoroughly instead of just ans ## Java Coding Style Preferences +### When using any form of auto-formatting, keep it to the actual change and make sure not to apply any auto-formatting to otherwise unchanged code. This would make reviewing a pain. + ### Variable Declarations - **Always use `final` where possible** for local variables, parameters, and fields - Prefer immutability diff --git a/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java b/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java index b1b1038fa37..4fc94230622 100755 --- a/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java +++ b/java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java @@ -63,6 +63,7 @@ import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.util.Holder; import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources; import com.sap.sse.gwt.client.EntryPointHelper; @@ -677,9 +678,8 @@ public class LandscapeManagementPanel extends SimplePanel { final Iterator> replicaSetIterator, StringMessages stringMessages) { assert replicaSetIterator.hasNext(); final SailingApplicationReplicaSetDTO replicaSet = replicaSetIterator.next(); - @SuppressWarnings("unchecked") - final Consumer[] issueRequest = new Consumer[1]; - issueRequest[0] = force -> landscapeManagementService.moveMasterToOtherInstance(replicaSet, + final Holder> issueRequest = new Holder<>(); + issueRequest.value = force -> landscapeManagementService.moveMasterToOtherInstance(replicaSet, instructions.isSharedMasterInstance(), instructions.getInstanceTypeOrNull(), sshKeyManagementPanel.getSelectedKeyPair() == null ? null : sshKeyManagementPanel.getSelectedKeyPair().getName(), sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption() != null ? sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption().getBytes() : null, @@ -713,13 +713,13 @@ public class LandscapeManagementPanel extends SimplePanel { showLiveContentWarning(result.getLiveContentCheckResult(), confirmed -> { if (confirmed) { applicationReplicaSetsBusy.setBusy(true); - issueRequest[0].accept(/* force */ true); + issueRequest.value.accept(/* force */ true); } }); } } }); - issueRequest[0].accept(/* force */ false); + issueRequest.value.accept(/* force */ false); } @Override @@ -1185,9 +1185,8 @@ public class LandscapeManagementPanel extends SimplePanel { @Override public void ok(String optionalInstanceTypeName) { applicationReplicaSetsBusy.setBusy(true); - @SuppressWarnings("unchecked") - final Consumer>[] issueRequest = new Consumer[1]; - issueRequest[0] = forceMasterReplicaSetNames -> landscapeManagementService.moveAllApplicationProcessesAwayFrom(fromHost, optionalInstanceTypeName, + final Holder>> issueRequest = new Holder<>(); + issueRequest.value = forceMasterReplicaSetNames -> landscapeManagementService.moveAllApplicationProcessesAwayFrom(fromHost, optionalInstanceTypeName, sshKeyManagementPanel.getSelectedKeyPair()==null?null:sshKeyManagementPanel.getSelectedKeyPair().getName(), sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption() != null ? sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption().getBytes() : null, @@ -1213,13 +1212,13 @@ public class LandscapeManagementPanel extends SimplePanel { showLiveContentWarning(result.getLiveContentCheckResult(), confirmed -> { if (confirmed) { applicationReplicaSetsBusy.setBusy(true); - issueRequest[0].accept(getConflictingReplicaSetNames(result.getLiveContentCheckResult())); + issueRequest.value.accept(getConflictingReplicaSetNames(result.getLiveContentCheckResult())); } }); } } }); - issueRequest[0].accept(Collections.emptySet()); + issueRequest.value.accept(Collections.emptySet()); } @Override @@ -1315,9 +1314,8 @@ public class LandscapeManagementPanel extends SimplePanel { final ApplicationReplicaSetActionChainingCallback applicationReplicaSetActionChainingCallback = new ApplicationReplicaSetActionChainingCallback(replicaSetIterator, applicationReplicaSetToRemove, (rId, rsi)->removeApplicationReplicaSet(rId, rsi, stringMessages), regionId, replicaSetName->stringMessages.successfullyRemovedApplicationReplicaSet(replicaSetName)); - @SuppressWarnings("unchecked") - final Consumer[] issueRequest = new Consumer[1]; - issueRequest[0] = force -> landscapeManagementService.removeApplicationReplicaSet(regionId, applicationReplicaSetToRemove, selectedMongoEndpointForDBArchiving, + final Holder> issueRequest = new Holder<>(); + issueRequest.value = force -> landscapeManagementService.removeApplicationReplicaSet(regionId, applicationReplicaSetToRemove, selectedMongoEndpointForDBArchiving, sshKeyManagementPanel.getSelectedKeyPair()==null?null:sshKeyManagementPanel.getSelectedKeyPair().getName(), sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption() != null ? sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption().getBytes() : null, @@ -1346,13 +1344,13 @@ public class LandscapeManagementPanel extends SimplePanel { showLiveContentWarning(result.getLiveContentCheckResult(), confirmed -> { if (confirmed) { applicationReplicaSetsBusy.setBusy(true); - issueRequest[0].accept(/* force */ true); + issueRequest.value.accept(/* force */ true); } }); } } }); - issueRequest[0].accept(/* force */ false); + issueRequest.value.accept(/* force */ false); } private static class ReplicaSetArchivingParameters { @@ -1397,9 +1395,8 @@ public class LandscapeManagementPanel extends SimplePanel { @Override public void ok(ReplicaSetArchivingParameters bearerTokensAndWhetherToRemoveReplicaSet) { applicationReplicaSetsBusy.setBusy(true); - @SuppressWarnings("unchecked") - final Consumer[] issueRequest = new Consumer[1]; - issueRequest[0] = force -> landscapeManagementService.archiveReplicaSet(regionId, applicationReplicaSetToArchive, + final Holder> issueRequest = new Holder<>(); + issueRequest.value = force -> landscapeManagementService.archiveReplicaSet(regionId, applicationReplicaSetToArchive, bearerTokensAndWhetherToRemoveReplicaSet.getBearerTokenOrNullForApplicationReplicaSetToArchive(), bearerTokensAndWhetherToRemoveReplicaSet.getBearerTokenOrNullForArchive(), bearerTokensAndWhetherToRemoveReplicaSet.getDurationToWaitBeforeAndBetweenCompareServerAttempts(), @@ -1426,7 +1423,7 @@ public class LandscapeManagementPanel extends SimplePanel { showLiveContentWarning(operationResult.getLiveContentCheckResult(), confirmed -> { if (confirmed) { applicationReplicaSetsBusy.setBusy(true); - issueRequest[0].accept(/* force */ true); + issueRequest.value.accept(/* force */ true); } }); } else { @@ -1457,7 +1454,7 @@ public class LandscapeManagementPanel extends SimplePanel { } } }); - issueRequest[0].accept(/* force */ false); + issueRequest.value.accept(/* force */ false); } @Override @@ -1620,9 +1617,8 @@ public class LandscapeManagementPanel extends SimplePanel { new Timer() { @Override public void run() { - @SuppressWarnings("unchecked") - final Consumer[] issueRequest = new Consumer[1]; - issueRequest[0] = force -> landscapeManagementService.upgradeApplicationReplicaSet(regionId, replicaSet, + final Holder> issueRequest = new Holder<>(); + issueRequest.value = force -> landscapeManagementService.upgradeApplicationReplicaSet(regionId, replicaSet, upgradeInstructions.getReleaseNameOrNullForLatestMaster(), sshKeyManagementPanel.getSelectedKeyPair()==null?null:sshKeyManagementPanel.getSelectedKeyPair().getName(), sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption() != null @@ -1654,13 +1650,13 @@ public class LandscapeManagementPanel extends SimplePanel { if (confirmed) { howManyMoreToGo[0]++; applicationReplicaSetsBusy.setBusy(true); - issueRequest[0].accept(/* force */ true); + issueRequest.value.accept(/* force */ true); } }); } } }); - issueRequest[0].accept(/* force */ false); + issueRequest.value.accept(/* force */ false); } }.schedule((int) timeToWaitUntilUpgradingNextReplicaSet.asMillis()); timeToWaitUntilUpgradingNextReplicaSet = timeToWaitUntilUpgradingNextReplicaSet.plus( diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/util/Holder.java b/java/com.sap.sse.common/src/com/sap/sse/common/util/Holder.java new file mode 100644 index 00000000000..2fa3e03d525 --- /dev/null +++ b/java/com.sap.sse.common/src/com/sap/sse/common/util/Holder.java @@ -0,0 +1,21 @@ +package com.sap.sse.common.util; + +/** + * A trivial mutable holder for a single reference, mirroring {@link IntHolder} and {@link DoubleHolder} for + * arbitrary object types. Useful, e.g., to give a lambda access to a value that can only be assigned after the + * lambda has been constructed, such as a recursively self-referencing lambda: the holder is declared first, the + * lambda captures the (effectively final) holder, and the lambda's own value is stored into {@link #value} + * afterwards. This avoids the {@code T[]} one-element-array idiom that would otherwise require an unchecked cast. + */ +public class Holder { + public T value; + + public Holder() { + super(); + } + + public Holder(T value) { + super(); + this.value = value; + } +}