This is an automated email from the ASF dual-hosted git repository. lhotari pushed a commit to branch branch-4.1 in repository https://gitbox.apache.org/repos/asf/pulsar.git
commit 8777ed6fc535f39b40737a42add883cb98e781a0 Author: Cong Zhao <[email protected]> AuthorDate: Mon Feb 9 16:03:25 2026 +0800 [fix][broker] Fix incomplete futures in topic property update/delete methods (#25228) (cherry picked from commit c2ae180a8f0eebdbbc45dd4b8f54ae1a7015d77d) --- .../broker/admin/impl/PersistentTopicsBase.java | 18 +++++++++++--- .../apache/pulsar/broker/admin/AdminApi2Test.java | 29 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java index 865212f48e5..a59326b333c 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java @@ -660,8 +660,10 @@ public class PersistentTopicsBase extends AdminResource { pulsar().getBrokerService().getTopicIfExists(topicName.toString()) .thenAccept(opt -> { if (!opt.isPresent()) { - throw new RestException(Status.NOT_FOUND, - getTopicNotFoundErrorMessage(topicName.toString())); + future.completeExceptionally( + new WebApplicationException(getTopicNotFoundErrorMessage(topicName.toString()), + Status.NOT_FOUND)); + return; } ManagedLedger managedLedger = ((PersistentTopic) opt.get()).getManagedLedger(); managedLedger.asyncSetProperties(properties, new AsyncCallbacks.UpdatePropertiesCallback() { @@ -681,6 +683,9 @@ public class PersistentTopicsBase extends AdminResource { future.completeExceptionally(exception); } }, null); + }).exceptionally(ex -> { + future.completeExceptionally(ex); + return null; }); return future; } @@ -717,8 +722,10 @@ public class PersistentTopicsBase extends AdminResource { pulsar().getBrokerService().getTopicIfExists(topicName.toString()) .thenAccept(opt -> { if (!opt.isPresent()) { - throw new RestException(Status.NOT_FOUND, - getTopicNotFoundErrorMessage(topicName.toString())); + future.completeExceptionally( + new WebApplicationException(getTopicNotFoundErrorMessage(topicName.toString()), + Status.NOT_FOUND)); + return; } ManagedLedger managedLedger = ((PersistentTopic) opt.get()).getManagedLedger(); managedLedger.asyncDeleteProperty(key, new AsyncCallbacks.UpdatePropertiesCallback() { @@ -733,6 +740,9 @@ public class PersistentTopicsBase extends AdminResource { future.completeExceptionally(exception); } }, null); + }).exceptionally(ex -> { + future.completeExceptionally(ex); + return null; }); return future; } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java index eeac3e1c5e2..b1c11e208d4 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java @@ -1412,6 +1412,35 @@ public class AdminApi2Test extends MockedPulsarServiceBaseTest { Assert.assertEquals(properties.get("key2"), "value2"); } + @Test + public void testUpdatePropertiesOnNonExistentTopic() throws Exception { + final String namespace = newUniqueName(defaultTenant + "/ns2"); + final String topicName = "persistent://" + namespace + "/testUpdatePropertiesOnNonExistentTopic"; + admin.namespaces().createNamespace(namespace, 20); + + // Test updateProperties on non-existent topic should return 404 Not Found + Map<String, String> topicProperties = new HashMap<>(); + topicProperties.put("key1", "value1"); + try { + admin.topics().updateProperties(topicName, topicProperties); + fail("Should have thrown an exception for non-existent topic"); + } catch (Exception e) { + Assert.expectThrows(PulsarAdminException.NotFoundException.class, () -> { + throw e; + }); + } + + // Test removeProperties on non-existent topic should return 404 Not Found + try { + admin.topics().removeProperties(topicName, "key1"); + fail("Should have thrown an exception for non-existent topic"); + } catch (PulsarAdminException.NotFoundException e) { + Assert.expectThrows(PulsarAdminException.NotFoundException.class, () -> { + throw e; + }); + } + } + @Test public void testNonPersistentTopics() throws Exception { final String namespace = newUniqueName(defaultTenant + "/ns2");
