From 3fd1eb08a0113fa499dd1a509da991709174948b Mon Sep 17 00:00:00 2001 From: Julien Nioche Date: Mon, 2 Mar 2026 18:14:12 +0000 Subject: [PATCH 1/2] Fix silent exception swallow in LocalFsBlobStore.prepare() If ClusterUtils.mkStormClusterState() threw (e.g. ZooKeeper unreachable), the exception was caught and printed to stderr via e.printStackTrace(), leaving stormClusterState null. Every subsequent blob store operation (startSyncBlobs, setupBlobstore, blobSync) would then crash with a NullPointerException rather than a meaningful error. Rethrow as RuntimeException to match the existing pattern used a few lines above for FileBlobStoreImpl initialization, and to surface the root cause at startup instead of at first use. Co-Authored-By: Claude Sonnet 4.6 --- .../main/java/org/apache/storm/blobstore/LocalFsBlobStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storm-server/src/main/java/org/apache/storm/blobstore/LocalFsBlobStore.java b/storm-server/src/main/java/org/apache/storm/blobstore/LocalFsBlobStore.java index f708946fbe2..3fcd5eedde7 100644 --- a/storm-server/src/main/java/org/apache/storm/blobstore/LocalFsBlobStore.java +++ b/storm-server/src/main/java/org/apache/storm/blobstore/LocalFsBlobStore.java @@ -110,7 +110,7 @@ public void prepare(Map conf, String overrideBase, NimbusInfo ni try { this.stormClusterState = ClusterUtils.mkStormClusterState(conf, new ClusterStateContext(DaemonType.NIMBUS, conf)); } catch (Exception e) { - e.printStackTrace(); + throw new RuntimeException("Failed to initialize cluster state for LocalFsBlobStore", e); } timer = new Timer("BLOB-STORE-TIMER", true); this.leaderElector = leaderElector; From e8216f735cad9812c0e5b1462168958dee8855e7 Mon Sep 17 00:00:00 2001 From: Julien Nioche Date: Tue, 3 Mar 2026 08:26:57 +0000 Subject: [PATCH 2/2] Fix tests that relied on silent exception swallowing in LocalFsBlobStore.prepare() Both tests called prepare() without a reachable ZooKeeper, relying on the now-fixed silent catch to let prepare() succeed with a null stormClusterState. LocalFsBlobStoreSynchronizerTest: add InProcessZookeeper to @BeforeEach/@AfterEach and pass its port in the conf used by initLocalFs(), matching the pattern already established in LocalFsBlobStoreTest. AsyncLocalizerTest.testKeyNotFoundException: wrap the test body in a try-with-resources InProcessZookeeper and pass its port in the conf, so that prepare() can initialise cluster state successfully before getBlob() is called to exercise the KeyNotFoundException path. Co-Authored-By: Claude Sonnet 4.6 --- .../LocalFsBlobStoreSynchronizerTest.java | 9 ++++-- .../storm/localizer/AsyncLocalizerTest.java | 28 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/storm-server/src/test/java/org/apache/storm/blobstore/LocalFsBlobStoreSynchronizerTest.java b/storm-server/src/test/java/org/apache/storm/blobstore/LocalFsBlobStoreSynchronizerTest.java index 7ba65b41ef4..f1f9473958e 100644 --- a/storm-server/src/test/java/org/apache/storm/blobstore/LocalFsBlobStoreSynchronizerTest.java +++ b/storm-server/src/test/java/org/apache/storm/blobstore/LocalFsBlobStoreSynchronizerTest.java @@ -30,6 +30,7 @@ import org.apache.storm.shade.org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.storm.shade.org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.storm.utils.Utils; +import org.apache.storm.testing.InProcessZookeeper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -46,6 +47,7 @@ public class LocalFsBlobStoreSynchronizerTest { private static Map conf = new HashMap<>(); private File baseFile; + private InProcessZookeeper zk; // Method which initializes nimbus admin @BeforeAll @@ -55,13 +57,15 @@ public static void initializeConfigs() { } @BeforeEach - public void init() { + public void init() throws Exception { baseFile = new File("target/blob-store-test-" + UUID.randomUUID()); + zk = new InProcessZookeeper(); } @AfterEach - public void cleanUp() throws IOException { + public void cleanUp() throws Exception { FileUtils.deleteDirectory(baseFile); + zk.close(); } private LocalFsBlobStore initLocalFs() { @@ -70,6 +74,7 @@ private LocalFsBlobStore initLocalFs() { conf.putAll(Utils.readStormConfig()); conf.put(Config.STORM_LOCAL_DIR, baseFile.getAbsolutePath()); conf.put(Config.STORM_PRINCIPAL_TO_LOCAL_PLUGIN, "org.apache.storm.security.auth.DefaultPrincipalToLocal"); + conf.put(Config.STORM_ZOOKEEPER_PORT, zk.getPort()); store.prepare(conf, null, null, null); return store; } diff --git a/storm-server/src/test/java/org/apache/storm/localizer/AsyncLocalizerTest.java b/storm-server/src/test/java/org/apache/storm/localizer/AsyncLocalizerTest.java index 1fef27cc004..1c55c1c6531 100644 --- a/storm-server/src/test/java/org/apache/storm/localizer/AsyncLocalizerTest.java +++ b/storm-server/src/test/java/org/apache/storm/localizer/AsyncLocalizerTest.java @@ -51,6 +51,7 @@ import org.apache.storm.generated.SettableBlobMeta; import org.apache.storm.generated.StormTopology; import org.apache.storm.security.auth.DefaultPrincipalToLocal; +import org.apache.storm.testing.InProcessZookeeper; import org.apache.storm.testing.TmpPath; import org.apache.storm.utils.ConfigUtils; import org.apache.storm.utils.ReflectionUtils; @@ -791,18 +792,21 @@ public void testFailAcls() { } @Test - public void testKeyNotFoundException() { - assertThrows(KeyNotFoundException.class, () -> { - Map conf = Utils.readStormConfig(); - String key1 = "key1"; - conf.put(Config.STORM_LOCAL_DIR, "target"); - LocalFsBlobStore bs = new LocalFsBlobStore(); - LocalFsBlobStore spy = spy(bs); - Mockito.doReturn(true).when(spy).checkForBlobOrDownload(key1); - Mockito.doNothing().when(spy).checkForBlobUpdate(key1); - spy.prepare(conf, null, null, null); - spy.getBlob(key1, null); - }); + public void testKeyNotFoundException() throws Exception { + try (InProcessZookeeper zk = new InProcessZookeeper()) { + assertThrows(KeyNotFoundException.class, () -> { + Map conf = Utils.readStormConfig(); + String key1 = "key1"; + conf.put(Config.STORM_LOCAL_DIR, "target"); + conf.put(Config.STORM_ZOOKEEPER_PORT, zk.getPort()); + LocalFsBlobStore bs = new LocalFsBlobStore(); + LocalFsBlobStore spy = spy(bs); + Mockito.doReturn(true).when(spy).checkForBlobOrDownload(key1); + Mockito.doNothing().when(spy).checkForBlobUpdate(key1); + spy.prepare(conf, null, null, null); + spy.getBlob(key1, null); + }); + } } @Test