This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 07ebe442 fix: reject updates for missing data sources (#581)
07ebe442 is described below
commit 07ebe4428e04f86d29bbe19bcb432384121f68b2
Author: yx9o <[email protected]>
AuthorDate: Wed Jul 29 10:08:17 2026 +0800
fix: reject updates for missing data sources (#581)
---
.../settings/InMemorySettingsRepository.java | 5 ++++
.../studio/settings/SettingsRepository.java | 2 ++
.../rocketmq/studio/settings/SettingsService.java | 6 +++-
.../settings/InMemorySettingsRepositoryTest.java | 32 ++++++++++++++++------
.../studio/settings/SettingsServiceTest.java | 20 ++++++++++++--
5 files changed, 53 insertions(+), 12 deletions(-)
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
b/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
index 46a1366b..ae72350e 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepository.java
@@ -65,6 +65,11 @@ public class InMemorySettingsRepository implements
SettingsRepository {
return dataSource;
}
+ @Override
+ public boolean replaceDataSource(DataSourceVO dataSource) {
+ return dataSources.replace(dataSource.getKey(), dataSource) != null;
+ }
+
@Override
public void deleteDataSource(String key) {
dataSources.remove(key);
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
index 0e6e2b9b..ecf24bf5 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsRepository.java
@@ -30,6 +30,8 @@ public interface SettingsRepository {
DataSourceVO saveDataSource(DataSourceVO dataSource);
+ boolean replaceDataSource(DataSourceVO dataSource);
+
void deleteDataSource(String key);
Optional<DataSourceVO> findDataSourceByKey(String key);
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
index d98a1cc5..6a49836d 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/settings/SettingsService.java
@@ -19,6 +19,7 @@ package org.apache.rocketmq.studio.settings;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.studio.common.exception.BusinessException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
@@ -101,7 +102,10 @@ public class SettingsService {
public DataSourceVO updateDataSource(DataSourceVO dataSource) {
log.info("Updating data source: {}", dataSource.getKey());
- return settingsRepository.saveDataSource(dataSource);
+ if (!settingsRepository.replaceDataSource(dataSource)) {
+ throw new BusinessException(404, "Data source not found: " +
dataSource.getKey());
+ }
+ return dataSource;
}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
b/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
index 7a30002f..373d3753 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/settings/InMemorySettingsRepositoryTest.java
@@ -25,7 +25,7 @@ class InMemorySettingsRepositoryTest {
private final InMemorySettingsRepository repository = new
InMemorySettingsRepository();
@Test
- void saveDataSourceShouldSupportCreateUpdateAndDeleteByKey() {
+ void saveDataSourceShouldSupportCreateAndDeleteByKey() {
DataSourceVO dataSource = DataSourceVO.builder()
.key("source-1")
.name("Prometheus")
@@ -38,17 +38,31 @@ class InMemorySettingsRepositoryTest {
assertThat(repository.findDataSourceByKey("source-1")).containsSame(dataSource);
assertThat(repository.findAllDataSources()).containsExactly(dataSource);
- dataSource.setName("Updated Prometheus");
- repository.saveDataSource(dataSource);
-
- assertThat(repository.findDataSourceByKey("source-1"))
- .get()
- .extracting(DataSourceVO::getName)
- .isEqualTo("Updated Prometheus");
-
repository.deleteDataSource("source-1");
assertThat(repository.findDataSourceByKey("source-1")).isEmpty();
assertThat(repository.findAllDataSources()).isEmpty();
}
+
+ @Test
+ void replaceDataSourceShouldUpdateExistingEntry() {
+ DataSourceVO existing =
DataSourceVO.builder().key("source-1").name("Prometheus").build();
+ DataSourceVO replacement =
DataSourceVO.builder().key("source-1").name("Updated Prometheus").build();
+ repository.saveDataSource(existing);
+
+ boolean replaced = repository.replaceDataSource(replacement);
+
+ assertThat(replaced).isTrue();
+
assertThat(repository.findAllDataSources()).containsExactly(replacement);
+ }
+
+ @Test
+ void replaceDataSourceShouldNotInsertUnknownEntry() {
+ DataSourceVO replacement =
DataSourceVO.builder().key("missing").name("Unexpected DS").build();
+
+ boolean replaced = repository.replaceDataSource(replacement);
+
+ assertThat(replaced).isFalse();
+ assertThat(repository.findAllDataSources()).isEmpty();
+ }
}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
b/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
index ba5f4d45..b7d09c82 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/settings/SettingsServiceTest.java
@@ -19,6 +19,7 @@ package org.apache.rocketmq.studio.settings;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
+import org.apache.rocketmq.studio.common.exception.BusinessException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -37,6 +38,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;
@@ -213,13 +215,27 @@ class SettingsServiceTest {
void updateDataSourceShouldDelegateToRepository() {
DataSourceVO input = DataSourceVO.builder().key("ds-1").name("Updated
DS").type("rocketmq")
.url("updated-host:9876").build();
-
when(settingsRepository.saveDataSource(any(DataSourceVO.class))).thenReturn(input);
+ when(settingsRepository.replaceDataSource(input)).thenReturn(true);
DataSourceVO result = settingsService.updateDataSource(input);
assertThat(result.getKey()).isEqualTo("ds-1");
assertThat(result.getName()).isEqualTo("Updated DS");
- verify(settingsRepository).saveDataSource(input);
+ verify(settingsRepository).replaceDataSource(input);
+ }
+
+ @Test
+ void updateDataSourceShouldRejectUnknownKey() {
+ SettingsService service = new SettingsService(new
InMemorySettingsRepository(), RestClient.builder(), new ObjectMapper());
+ DataSourceVO input =
DataSourceVO.builder().key("missing").name("Unexpected DS").type("rocketmq")
+ .url("unexpected-host:9876").build();
+
+ assertThatThrownBy(() -> service.updateDataSource(input))
+ .isInstanceOf(BusinessException.class)
+ .hasMessage("Data source not found: missing")
+ .extracting("code")
+ .isEqualTo(404);
+ assertThat(service.listDataSources()).isEmpty();
}
@Test