Skip to content

Conversation

@KomachiSion
Copy link
Collaborator

Please do not create a Pull Request without creating an issue first.

What is the purpose of the change

XXXXX

Brief changelog

XX

Verifying this change

XXXX

Follow this checklist to help us incorporate your contribution quickly and easily:

  • Make sure there is a Github issue filed for the change (usually before you start working on it). Trivial changes like typos do not require a Github issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
  • Format the pull request title like [ISSUE #123] Fix UnknownException when host config not exist. Each commit in the pull request should have a meaningful subject line and body.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add integration-test in test module.
  • Run mvn -B clean package apache-rat:check findbugs:findbugs -Dmaven.test.skip=true to make sure basic checks pass. Run mvn clean install -DskipITs to make sure unit-test pass. Run mvn clean test-compile failsafe:integration-test to make sure integration-test pass.

@KomachiSion KomachiSion added this to the 3.0.3 milestone Jul 22, 2025
@KomachiSion KomachiSion added kind/bug Category issues or prs related to bug. area/Naming labels Jul 22, 2025
@lingma-agents
Copy link

lingma-agents bot commented Jul 22, 2025

修复更新实例元数据时空值导致的NPE并添加测试用例

变更概述

问题修复

  • 修复InstanceOperatorClientImpl在元数据包含空值时引发的NullPointerException
    • 修改buildMetadata方法,通过filterNullValue过滤掉元数据中的空值
    • 使用Java 8 Stream API实现空值过滤逻辑(Collectors.toMap
    • 解决因直接复制原始元数据(instance.getMetadata())导致的潜在空值注入问题

测试更新

  • 新增testUpdateInstanceWithNullValue测试用例
    • 验证当元数据包含空值时,ExtendData字段不会存储空值
    • 使用Mockito断言updateInstanceMetadata参数的ExtendData为空对象
变更文件
文件路径 变更说明
naming/​src/​main/​java/​com/​alibaba/​nacos/​naming/​core/​InstanceOperatorClientImpl.​java 添加空值过滤逻辑到元数据处理流程,避免空指针异常
naming/​src/​test/​java/​com/​alibaba/​nacos/​naming/​core/​InstanceOperatorClientImplTest.​java 新增测试覆盖元数据空值场景
时序图
sequenceDiagram
    participant IOC as InstanceOperatorClientImpl
    participant M as InstanceMetadata
    participant T as testUpdateInstanceWithNullValue
    T->>IOC: 调用updateInstance()
    IOC->>IOC: buildMetadata()
    IOC->>IOC: filterNullValue()
    IOC->>M: 构建过滤后的ExtendData
    IOC->>M: 排除null值的元数据
    IOC-->>T: 返回清理后的元数据
Loading

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

Copy link

@lingma-agents lingma-agents bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 代码评审报告

🎯 评审意见概览
严重度 数量 说明
🔴 Blocker 0 阻断性问题,需立即修复。例如:系统崩溃、关键功能不可用或严重安全漏洞。
🟠 Critical 1 严重问题,高优先级修复。例如:核心功能异常或性能瓶颈影响用户体验。
🟡 Major 1 主要问题,建议修复。例如:非核心功能缺陷或代码维护性较差。
🟢 Minor 0 次要问题,酬情优化。例如:代码格式不规范或注释缺失。

总计: 2 个问题

📋 评审意见详情
💡 代码实现建议
以下是文件级别的代码建议,聚焦于代码的可读性、可维护性和潜在问题。
☕ naming/src/main/java/com/alibaba/nacos/naming/core/InstanceOperatorClientImpl.java (1 💬)
☕ naming/src/test/java/com/alibaba/nacos/naming/core/InstanceOperatorClientImplTest.java (1 💬)
🚀 架构设计建议
以下是对代码架构和设计的综合分析,聚焦于跨文件交互、系统一致性和潜在优化空间。
🔍1. 测试覆盖不全面:未测试metadata为null的情况

新增的测试用例testUpdateInstanceWithNullValue仅验证了metadata中存在null值的条目,但未覆盖metadata本身为null的场景。若调用instance.getMetadata()返回null时,当前代码仍会抛出空指针异常。建议补充测试用例,模拟metadata为null的情况,确保系统在极端输入下健壮性。

⚠️ 潜在风险

若metadata为null时未被处理,可能导致系统在生产环境中出现不可预测的空指针异常,影响服务稳定性。

🔍2. 跨文件潜在NPE风险:未统一处理metadata的null情况

当前修复仅在InstanceOperatorClientImpl中添加了过滤null值的逻辑,但未确保其他调用instance.getMetadata()的模块(如其他服务或业务逻辑)同样处理了metadata为null的情况。例如,若存在其他组件直接使用instance.getMetadata()而未进行null检查,仍可能导致NPE。建议在架构层面统一规范metadata的处理逻辑,或在Instance类中强制初始化metadata为不可null的Map。

⚠️ 潜在风险

其他未修复的调用点可能遗留NPE风险,导致系统不同模块间行为不一致,增加排查问题的复杂度。

🔍3. 架构一致性问题:未在源头确保metadata非null

Instance类的metadata字段可能为null,但根据领域模型设计,metadata应始终为有效的Map。建议在Instance类的构造函数或初始化方法中强制将metadata初始化为空Map(如metadata = metadata == null ? new HashMap() : metadata),从而在源头避免null值的传播。当前的修复仅在使用端处理,未能从根源解决问题,可能增加长期维护成本。

⚠️ 潜在风险

未在源头处理可能导致多个模块需要重复编写null检查逻辑,违背DRY原则,增加冗余代码和潜在遗漏风险。

审查详情
📒 文件清单 (2 个文件)
📝 变更: 2 个文件

📝 变更文件:

  • naming/src/main/java/com/alibaba/nacos/naming/core/InstanceOperatorClientImpl.java
  • naming/src/test/java/com/alibaba/nacos/naming/core/InstanceOperatorClientImplTest.java

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

Comment on lines +152 to +155
private Map<String, String> filterNullValue(Map<String, String> metadata) {
return metadata.entrySet().stream().filter(entry -> entry.getValue() != null)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

未处理metadata为null的情况可能导致空指针异常

🟠 Critical | 🐞 Bugs

📋 问题详情

当传入的metadata参数为null时,filterNullValue方法会尝试访问其entrySet(),导致NullPointerException。需要添加对null值的检查,返回空map以避免异常。

💡 解决方案

filterNullValue方法中添加对metadata为null的检查,返回空map以避免空指针异常。

-private Map<String, String> filterNullValue(Map<String, String> metadata) {
-    return metadata.entrySet().stream().filter(entry -> entry.getValue() != null)
-            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
-}
+private Map<String, String> filterNullValue(Map<String, String> metadata) {
+    if (metadata == null) {
+        return Collections.emptyMap();
+    }
+    return metadata.entrySet().stream()
+            .filter(entry -> entry.getValue() != null)
+            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+}

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

Comment on lines +167 to +175
@Test
void testUpdateInstanceWithNullValue() throws NacosException {
Instance instance = new Instance();
instance.setServiceName("C");
instance.getMetadata().put("nullValue", null);
instanceOperatorClient.updateInstance("A", Constants.DEFAULT_GROUP, "C", instance);

Mockito.verify(metadataOperateService).updateInstanceMetadata(Mockito.any(), Mockito.any(),
Mockito.argThat(argument -> argument.getExtendData().isEmpty()));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

未覆盖instance.getMetadata()为null的测试用例

🟡 Major | 🧹 Code Smells

📋 问题详情

当前测试用例仅测试了元数据条目值为null的情况,但未验证当instance.getMetadata()返回null时的处理。需要添加测试用例以确保该场景下方法正确返回空map,避免NPE。

💡 解决方案

添加测试用例testUpdateInstanceWithNullMetadata,验证当instance.getMetadata()返回null时,filterNullValue方法返回空map,确保不会抛出NPE。

@@ -176,4 +176,20 @@
     Mockito.argThat(argument -> argument.getExtendData().isEmpty()));
 }
 
+    @Test
+    void testUpdateInstanceWithNullMetadata() throws NacosException {
+        Instance instance = new Instance();
+        instance.setServiceName("C");
+        instance.setMetadata(null); // 设置metadata为null
+        instanceOperatorClient.updateInstance("A", Constants.DEFAULT_GROUP, "C", instance);
+        
+        Mockito.verify(metadataOperateService).updateInstanceMetadata(Mockito.any(), Mockito.any(),
+                Mockito.argThat(argument -> argument.getExtendData().isEmpty()));
+    }
+    
 @Test
 void testPatchInstance() throws NacosException {

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

@github-actions
Copy link

Thanks for your this PR. 🙏
Please check again for your PR changes whether contains any usage/api/configuration change such as Add new API , Add new configuration, Change default value of configuration.
If so, please add or update documents(markdown type) in docs/next/ for repository nacos-group/nacos-group.github.io


感谢您提交的PR。 🙏
请再次查看您的PR内容,确认是否包含任何使用方式/API/配置参数的变更,如:新增API新增配置参数修改默认配置等操作。
如果是,请确保在提交之前,在仓库nacos-group/nacos-group.github.io中的docs/next/目录下添加或更新文档(markdown格式)。

@KomachiSion KomachiSion merged commit c4b7ce8 into alibaba:develop Jul 22, 2025
5 checks passed
@KomachiSion KomachiSion deleted the upstream-develop-fix-update-metadata-with-null-value branch July 22, 2025 11:14
@wuyfee
Copy link

wuyfee commented Jul 22, 2025

$\color{red}{FAILURE}$
DETAILS
✅ - docker: success
❌ - deploy (standalone & cluster & standalone_auth): failure
❌ - e2e-java-test (standalone & cluster & standalone_auth): skipped
❌ - e2e-go-test (standalone & cluster): skipped
❌ - e2e-cpp-test (standalone & cluster): skipped
❌ - e2e-csharp-test (standalone & cluster): skipped
❌ - e2e-nodejs-test (standalone & cluster): skipped
❌ - e2e-python-test (standalone & cluster): skipped
✅ - clean (standalone & cluster & standalone_auth): success

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/Naming kind/bug Category issues or prs related to bug.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants