This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new e8795e98eb Add MongoDB 5.x plugin, Jedis 5.x support, fix Spring MVC 
javax/jakarta detection (#803)
e8795e98eb is described below

commit e8795e98eb67fb6587bc64f28c2aa4e619ed7f6f
Author: 吴晟 Wu Sheng <[email protected]>
AuthorDate: Thu Apr 9 20:03:42 2026 +0800

    Add MongoDB 5.x plugin, Jedis 5.x support, fix Spring MVC javax/jakarta 
detection (#803)
    
    ## Summary
    - Add MongoDB driver 5.x support (new plugin module for 5.2+, extend 4.x 
for 5.0-5.1)
    - Extend Jedis 4.x plugin to support Jedis 5.x (witness method fix)
    - Fix Spring MVC plugin javax/jakarta servlet detection when both exist on 
classpath
    - Document package-private class access pattern for plugins
    
    ## MongoDB 5.0-5.1 (4.x plugin extended)
    Added versions to support-version.list. Same MongoClientDelegate API.
    
    ## MongoDB 5.2+ (new mongodb-5.x-plugin module)
    MongoClusterImpl replaces MongoClientDelegate. New interceptors with 
remotePeer propagation via setAccessible reflection (MongoClusterImpl is 
package-private).
    
    ## Jedis 5.x (4.x plugin witness fix)
    All intercepted classes unchanged in 5.x. Plugin was silently not 
activating because witness Pipeline.persist(1 arg) moved to parent 
PipeliningBase. Changed witness to Connection.executeCommand(1 arg).
    
    Resolves https://github.com/apache/skywalking/issues/11747
    
    ## Spring MVC javax/jakarta fix
    When both javax.servlet and jakarta.servlet exist on classpath, the 
exclusive if/else set IS_JAVAX=true and skipped Jakarta check. Fix: check both 
independently.
    
    Ref: https://github.com/apache/skywalking/discussions/13425
---
 .claude/skills/new-plugin/SKILL.md                 |  11 ++
 .github/workflows/plugins-test.1.yaml              |   1 +
 .gitignore                                         |   1 +
 CHANGES.md                                         |   1 +
 apm-sniffer/apm-sdk-plugin/CLAUDE.md               |  19 +++
 .../v4/define/AbstractWitnessInstrumentation.java  |   7 +-
 .../apm-sdk-plugin/mongodb-5.x-plugin/pom.xml      |  50 +++++++
 .../v5/define/MongoClusterImplInstrumentation.java |  92 ++++++++++++
 ...ngoClusterOperationExecutorInstrumentation.java | 107 ++++++++++++++
 .../MongoClusterImplConstructorInterceptor.java    |  89 +++++++++++
 ...perationExecutorImplConstructorInterceptor.java |  53 +++++++
 .../src/main/resources/skywalking-plugin.def       |   8 +-
 apm-sniffer/apm-sdk-plugin/pom.xml                 |   1 +
 .../interceptor/AbstractMethodInterceptor.java     |  20 +--
 .../java-agent/Java-Plugin-Development-Guide.md    |  23 +++
 .../setup/service-agent/java-agent/Plugin-list.md  |   1 +
 .../service-agent/java-agent/Supported-list.md     |   4 +-
 .../jedis-4.x-scenario/support-version.list        |   1 +
 .../mongodb-4.x-scenario/support-version.list      |   5 +-
 .../bin/startup.sh}                                |  10 +-
 .../mongodb-5.x-scenario/config/expectedData.yaml  | 162 +++++++++++++++++++++
 .../configuration.yml}                             |  13 +-
 test/plugin/scenarios/mongodb-5.x-scenario/pom.xml | 148 +++++++++++++++++++
 .../src/main/assembly/assembly.xml                 |  41 ++++++
 .../apm/testcase/mongodb/Application.java          |  34 +++++
 .../mongodb/controller/CaseController.java         |  95 ++++++++++++
 .../src/main/resources/application.yaml            |  25 ++++
 .../src/main/resources/log4j2.xml                  |  30 ++++
 .../support-version.list                           |   8 +-
 29 files changed, 1026 insertions(+), 34 deletions(-)

diff --git a/.claude/skills/new-plugin/SKILL.md 
b/.claude/skills/new-plugin/SKILL.md
index 08dc73d0f1..d960d07058 100644
--- a/.claude/skills/new-plugin/SKILL.md
+++ b/.claude/skills/new-plugin/SKILL.md
@@ -57,6 +57,17 @@ Pick interception points based on these principles:
 **Principle 1: Data accessibility without reflection.**
 Choose methods where the information you need (peer address, operation name, 
request/response details, headers for inject/extract) is directly available as 
method arguments, return values, or accessible through the `this` object's 
public API. **Never use reflection to read private fields.** If the data is not 
accessible at one method, look at a different point in the execution flow.
 
+If the target class is **package-private** (e.g., `final class` without 
`public`), you cannot import or cast to it. **Same-package helper classes do 
NOT work** because the agent and application use different classloaders — Java 
treats them as different runtime packages even with the same package name 
(`IllegalAccessError`). Use `setAccessible` reflection to call public methods:
+```java
+try {
+    java.lang.reflect.Method method = 
objInst.getClass().getMethod("publicMethodName");
+    method.setAccessible(true);  // Required for package-private class
+    Object result = method.invoke(objInst);
+} catch (Exception e) {
+    LOGGER.warn("Failed to access method", e);
+}
+```
+
 **Principle 2: Use `EnhancedInstance` dynamic field to propagate context 
inside the library.**
 This is the primary mechanism for passing data between interception points. 
The agent adds a dynamic field to every enhanced class via `EnhancedInstance`. 
Use it to:
 - Store server address (peer) at connection/client creation time, retrieve it 
at command execution time
diff --git a/.github/workflows/plugins-test.1.yaml 
b/.github/workflows/plugins-test.1.yaml
index 21d5f04eab..19e20deb5c 100644
--- a/.github/workflows/plugins-test.1.yaml
+++ b/.github/workflows/plugins-test.1.yaml
@@ -91,6 +91,7 @@ jobs:
           - lettuce-webflux-5x-scenario
           - mongodb-3.x-scenario
           - mongodb-4.x-scenario
+          - mongodb-5.x-scenario
           - netty-socketio-scenario
           - postgresql-above9.4.1207-scenario
           - mssql-jtds-scenario
diff --git a/.gitignore b/.gitignore
index e127805e50..da77f29d42 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ packages/
 /test/jacoco/classes
 /test/jacoco/*.exec
 test/jacoco
+.claude/settings.local.json
diff --git a/CHANGES.md b/CHANGES.md
index bb89a9e688..ad1e3f6c51 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -20,6 +20,7 @@ Release Notes.
 * Extend Spring Kafka plugin to support Spring Kafka 2.4 -> 2.9 and 3.0 -> 3.3.
 * Enhance test/plugin/run.sh to support extra Maven properties per version in 
support-version.list (format: version,key=value).
 * Add MariaDB 3.x plugin (all classes renamed in 3.x).
+* Extend Jedis 4.x plugin to support Jedis 5.x (fix witness method for 5.x 
compatibility).
 
 All issues and pull requests are 
[here](https://github.com/apache/skywalking/milestone/249?closed=1)
 
diff --git a/apm-sniffer/apm-sdk-plugin/CLAUDE.md 
b/apm-sniffer/apm-sdk-plugin/CLAUDE.md
index eb88c1cbe1..b839fbe73b 100644
--- a/apm-sniffer/apm-sdk-plugin/CLAUDE.md
+++ b/apm-sniffer/apm-sdk-plugin/CLAUDE.md
@@ -145,6 +145,25 @@ public class MyPluginConfig {
 ```
 Config key becomes: `plugin.myplugin.some_setting`
 
+### Accessing Package-Private Classes
+
+When a plugin needs to call methods on a **package-private** class in the 
target library (e.g., `MongoClusterImpl` which is `final class` without 
`public`), you cannot import or cast to it from the plugin package.
+
+**Same-package helper classes do NOT work** because the agent and application 
use different classloaders. Even though the package names match, Java considers 
them different runtime packages, so package-private access is denied 
(`IllegalAccessError`).
+
+**Solution: use `setAccessible` reflection** to call public methods on 
package-private classes:
+```java
+try {
+    java.lang.reflect.Method method = 
objInst.getClass().getMethod("publicMethodName");
+    method.setAccessible(true);  // Required for package-private class
+    Object result = method.invoke(objInst);
+} catch (Exception e) {
+    LOGGER.warn("Failed to access method", e);
+}
+```
+
+**When to use:** Only when the target class is package-private and you need to 
call its public methods. Prefer normal casting when the class is public.
+
 ### Dependency Management
 
 **Plugin dependencies must use `provided` scope:**
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java
index 8c736751a3..03e5dc6792 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java
@@ -35,8 +35,11 @@ public abstract class AbstractWitnessInstrumentation extends 
ClassInstanceMethod
 
     @Override
     protected List<WitnessMethod> witnessMethods() {
+        // Connection.executeCommand(CommandObject) exists in Jedis 4.x+ and 
5.x,
+        // but not in 3.x. Previous witness Pipeline.persist(1) broke in 5.x
+        // because persist moved from Pipeline to PipeliningBase parent class.
         return Collections.singletonList(new WitnessMethod(
-                "redis.clients.jedis.Pipeline",
-                named("persist").and(takesArguments(1))));
+                "redis.clients.jedis.Connection",
+                named("executeCommand").and(takesArguments(1))));
     }
 }
diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml
new file mode 100644
index 0000000000..141dbd464a
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>apm-sdk-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>9.7.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>apm-mongodb-5.x-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <name>mongodb-5.x-plugin</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongodb-driver-sync</artifactId>
+            <version>5.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>apm-mongodb-4.x-plugin</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git 
a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java
 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java
new file mode 100644
index 0000000000..96b834fbca
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.mongodb.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static 
org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
+import static 
org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * Enhance {@code com.mongodb.client.internal.MongoClusterImpl} which replaces
+ * {@code MongoClientDelegate} in MongoDB driver 5.2+.
+ * Extract remotePeer from Cluster (constructor arg[1]) and store in dynamic 
field.
+ */
+public class MongoClusterImplInstrumentation extends 
ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = 
"com.mongodb.client.internal.MongoClusterImpl";
+
+    private static final String CONSTRUCTOR_INTERCEPTOR =
+        
"org.apache.skywalking.apm.plugin.mongodb.v5.interceptor.MongoClusterImplConstructorInterceptor";
+
+    @Override
+    protected String[] witnessClasses() {
+        return new String[] {ENHANCE_CLASS};
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[] {
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> 
getConstructorMatcher() {
+                    return takesArgumentWithType(1, 
"com.mongodb.internal.connection.Cluster");
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return CONSTRUCTOR_INTERCEPTOR;
+                }
+            }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() 
{
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("getOperationExecutor");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return CONSTRUCTOR_INTERCEPTOR;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java
 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java
new file mode 100644
index 0000000000..53bdb6da93
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.mongodb.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+import 
org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
+
+/**
+ * Enhance {@code MongoClusterImpl$OperationExecutorImpl} in MongoDB driver 
5.2+.
+ * <p>
+ * Constructor interception: propagate remotePeer from enclosing 
MongoClusterImpl
+ * (synthetic arg[0] for non-static inner class).
+ * <p>
+ * Method interception: create exit spans on execute() calls.
+ * Reuses the 4.x MongoDBOperationExecutorInterceptor.
+ */
+public class MongoClusterOperationExecutorInstrumentation extends 
ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS =
+        "com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl";
+
+    private static final String CONSTRUCTOR_INTERCEPTOR =
+        
"org.apache.skywalking.apm.plugin.mongodb.v5.interceptor.OperationExecutorImplConstructorInterceptor";
+
+    private static final String EXECUTE_INTERCEPTOR =
+        
"org.apache.skywalking.apm.plugin.mongodb.v4.interceptor.MongoDBOperationExecutorInterceptor";
+
+    private static final String METHOD_NAME = "execute";
+
+    private static final String ARGUMENT_TYPE = 
"com.mongodb.client.ClientSession";
+
+    @Override
+    protected String[] witnessClasses() {
+        return new String[] {"com.mongodb.client.internal.MongoClusterImpl"};
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return NameMatch.byName(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[] {
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> 
getConstructorMatcher() {
+                    return ElementMatchers.any();
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return CONSTRUCTOR_INTERCEPTOR;
+                }
+            }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() 
{
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return ElementMatchers
+                        .named(METHOD_NAME)
+                        .and(ArgumentTypeNameMatch.takesArgumentWithType(2, 
ARGUMENT_TYPE))
+                        
.or(ElementMatchers.<MethodDescription>named(METHOD_NAME)
+                            
.and(ArgumentTypeNameMatch.takesArgumentWithType(3, ARGUMENT_TYPE)));
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return EXECUTE_INTERCEPTOR;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java
new file mode 100644
index 0000000000..242b450c45
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.mongodb.v5.interceptor;
+
+import com.mongodb.internal.connection.Cluster;
+import org.apache.skywalking.apm.agent.core.logging.api.ILog;
+import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import 
org.apache.skywalking.apm.plugin.mongodb.v4.support.MongoRemotePeerHelper;
+
+import java.lang.reflect.Method;
+
+/**
+ * Intercept {@code MongoClusterImpl} constructor and {@code 
getOperationExecutor()}.
+ * <p>
+ * Constructor: extract remotePeer from Cluster (arg[1]) and store in dynamic 
field.
+ * getOperationExecutor(): pass remotePeer to the returned OperationExecutor.
+ */
+public class MongoClusterImplConstructorInterceptor
+    implements InstanceConstructorInterceptor, 
InstanceMethodsAroundInterceptor {
+
+    private static final ILog LOGGER = 
LogManager.getLogger(MongoClusterImplConstructorInterceptor.class);
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+        Cluster cluster = (Cluster) allArguments[1];
+        String remotePeer = MongoRemotePeerHelper.getRemotePeer(cluster);
+        objInst.setSkyWalkingDynamicField(remotePeer);
+
+        // The OperationExecutorImpl is created INSIDE this constructor 
(before onConstruct fires),
+        // so its constructor interceptor couldn't read the peer yet. Set it 
now.
+        // MongoClusterImpl is package-private and loaded by application 
classloader.
+        // Same-package helpers from agent classloader cannot access it 
(different runtime packages).
+        // Use setAccessible reflection to call getOperationExecutor().
+        try {
+            java.lang.reflect.Method getExecutor = 
objInst.getClass().getMethod("getOperationExecutor");
+            getExecutor.setAccessible(true);
+            Object executor = getExecutor.invoke(objInst);
+            if (executor instanceof EnhancedInstance) {
+                ((EnhancedInstance) 
executor).setSkyWalkingDynamicField(remotePeer);
+            }
+        } catch (Exception e) {
+            LOGGER.warn("Failed to set remotePeer on OperationExecutor", e);
+        }
+    }
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] 
allArguments,
+        Class<?>[] argumentsTypes, MethodInterceptResult result) {
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, 
Object[] allArguments,
+        Class<?>[] argumentsTypes, Object ret) {
+        if (ret instanceof EnhancedInstance) {
+            EnhancedInstance retInstance = (EnhancedInstance) ret;
+            String remotePeer = (String) objInst.getSkyWalkingDynamicField();
+            if (LOGGER.isDebugEnable()) {
+                LOGGER.debug("Mark OperationExecutor remotePeer: {}", 
remotePeer);
+            }
+            retInstance.setSkyWalkingDynamicField(remotePeer);
+        }
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, 
Object[] allArguments,
+        Class<?>[] argumentsTypes, Throwable t) {
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.java
new file mode 100644
index 0000000000..0b7c11862e
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.mongodb.v5.interceptor;
+
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * Intercept {@code MongoClusterImpl$OperationExecutorImpl} constructor.
+ * As a non-static inner class, the compiled constructor has the enclosing
+ * {@code MongoClusterImpl} instance as a synthetic first argument (arg index 
0).
+ *
+ * Note: This interceptor fires during MongoClusterImpl's constructor, before
+ * MongoClusterImpl.onConstruct() sets the remotePeer. So the dynamic field
+ * on the enclosing instance is not yet set. The primary peer propagation
+ * happens in MongoClusterImplConstructorInterceptor.onConstruct() which
+ * calls getOperationExecutor() after the constructor completes.
+ *
+ * This interceptor serves as a secondary path for OperationExecutorImpl
+ * instances created later (e.g., via withTimeoutSettings()).
+ */
+public class OperationExecutorImplConstructorInterceptor implements 
InstanceConstructorInterceptor {
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+        for (Object arg : allArguments) {
+            if (arg instanceof EnhancedInstance) {
+                EnhancedInstance enclosingInstance = (EnhancedInstance) arg;
+                String remotePeer = (String) 
enclosingInstance.getSkyWalkingDynamicField();
+                if (remotePeer != null && !remotePeer.isEmpty()) {
+                    objInst.setSkyWalkingDynamicField(remotePeer);
+                    return;
+                }
+            }
+        }
+    }
+}
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def
similarity index 74%
copy from test/plugin/scenarios/jedis-4.x-scenario/support-version.list
copy to 
apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def
index 31258966c3..fcd2e7be8f 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
+++ 
b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def
@@ -14,8 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-4.4.6
-4.3.2
-4.2.3
-4.1.1
-4.0.1
+# MongoDB 5.2+ (MongoClusterImpl replaces MongoClientDelegate)
+mongodb-5.x=org.apache.skywalking.apm.plugin.mongodb.v5.define.MongoClusterImplInstrumentation
+mongodb-5.x=org.apache.skywalking.apm.plugin.mongodb.v5.define.MongoClusterOperationExecutorInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml 
b/apm-sniffer/apm-sdk-plugin/pom.xml
index fca054b6a5..775ec34e12 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -37,6 +37,7 @@
         <module>motan-plugin</module>
         <module>mongodb-3.x-plugin</module>
         <module>mongodb-4.x-plugin</module>
+        <module>mongodb-5.x-plugin</module>
         <module>feign-default-http-9.x-plugin</module>
         <module>okhttp-3.x-plugin</module>
         <module>okhttp-4.x-plugin</module>
diff --git 
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
index ac51e60b93..67f2709c8f 100644
--- 
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
@@ -74,19 +74,21 @@ public abstract class AbstractMethodInterceptor implements 
InstanceMethodsAround
             AbstractMethodInterceptor.class.getClassLoader(),
             JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD
         );
+        // Check both javax and jakarta independently — both may exist on the 
classpath.
+        // For example, a Spring MVC 6.x (Jakarta) app may have javax.servlet 
as a
+        // transitive dependency. The runtime request type determines which 
path is used.
         try {
             Class.forName(SERVLET_RESPONSE_CLASS, true, 
AbstractMethodInterceptor.class.getClassLoader());
-            IN_SERVLET_CONTAINER = true;
             IS_JAVAX = true;
+            IN_SERVLET_CONTAINER = true;
+        } catch (Exception ignore) {
+        }
+        try {
+            Class.forName(
+                JAKARTA_SERVLET_RESPONSE_CLASS, true, 
AbstractMethodInterceptor.class.getClassLoader());
+            IS_JAKARTA = true;
+            IN_SERVLET_CONTAINER = true;
         } catch (Exception ignore) {
-            try {
-                Class.forName(
-                    JAKARTA_SERVLET_RESPONSE_CLASS, true, 
AbstractMethodInterceptor.class.getClassLoader());
-                IN_SERVLET_CONTAINER = true;
-                IS_JAKARTA = true;
-            } catch (Exception ignore2) {
-                IN_SERVLET_CONTAINER = false;
-            }
         }
     }
 
diff --git 
a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md 
b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md
index 0498f2011d..201835a1dc 100644
--- a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md
+++ b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md
@@ -621,3 +621,26 @@ Please follow these steps:
 1. Send a pull request and ask for review.
 1. The plugin committers will approve your plugins, plugin CI-with-IT, e2e, 
and the plugin tests will be passed.
 1. The plugin is accepted by SkyWalking.
+
+### Accessing package-private target classes
+
+When a plugin needs to call methods on a **package-private** class in the 
target library (e.g., `MongoClusterImpl` which is `final class` without 
`public`), you cannot import or cast to it from the plugin's 
`org.apache.skywalking` package.
+
+**Important:** Same-package helper classes do NOT work because the agent and 
application use different classloaders. Java treats them as different runtime 
packages even with identical package names, so package-private access is denied 
with `IllegalAccessError`.
+
+**Solution:** Use `setAccessible` reflection to call public methods on 
package-private classes:
+
+```java
+try {
+    java.lang.reflect.Method method = 
objInst.getClass().getMethod("publicMethodName");
+    method.setAccessible(true);  // Required: class is package-private
+    Object result = method.invoke(objInst);
+    if (result instanceof EnhancedInstance) {
+        ((EnhancedInstance) result).setSkyWalkingDynamicField(value);
+    }
+} catch (Exception e) {
+    logger.warn("Failed to access method", e);
+}
+```
+
+**When to use:** Only when the target class is package-private and you need to 
call its public methods. Prefer normal casting in interceptors when the class 
is public.
diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md 
b/docs/en/setup/service-agent/java-agent/Plugin-list.md
index a829e1a174..2bfd58f872 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -70,6 +70,7 @@
 - mongodb-2.x
 - mongodb-3.x
 - mongodb-4.x
+- mongodb-5.x
 - motan-0.x
 - mybatis-3.x
 - mysql-5.x
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md 
b/docs/en/setup/service-agent/java-agent/Supported-list.md
index a875618a02..772f169c39 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -88,10 +88,10 @@ metrics based on the tracing data.
 * NoSQL
   * [aerospike](https://github.com/aerospike/aerospike-client-java) 3.x -> 6.x
   * Redis
-    * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x
+    * [Jedis](https://github.com/xetorthio/jedis) 2.x-5.x
     * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 
3.5.0 -> 3.30.0 
     * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x -> 6.7.1
-  * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 
2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.11.5
+  * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 
2.13-2.14, 3.4.0-3.12.7, 4.0.0-5.5.x
   * Memcached Client
     * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x
     * [Xmemcached](https://github.com/killme2008/xmemcached) 2.x
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list 
b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
index 31258966c3..7545c1ec00 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
+++ b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
@@ -19,3 +19,4 @@
 4.2.3
 4.1.1
 4.0.1
+5.2.0
diff --git a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list 
b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list
index 42c7e89fb5..ec4ce41a71 100644
--- a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list
+++ b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list
@@ -25,4 +25,7 @@
 4.8.2
 4.9.1
 4.10.2
-4.11.5
\ No newline at end of file
+4.11.5
+# 5.0-5.1 still uses MongoClientDelegate (same as 4.x)
+5.0.1
+5.1.4
\ No newline at end of file
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list 
b/test/plugin/scenarios/mongodb-5.x-scenario/bin/startup.sh
similarity index 83%
copy from test/plugin/scenarios/jedis-4.x-scenario/support-version.list
copy to test/plugin/scenarios/mongodb-5.x-scenario/bin/startup.sh
index 31258966c3..8d9acc35ea 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/bin/startup.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+#
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
@@ -14,8 +16,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-4.4.6
-4.3.2
-4.2.3
-4.1.1
-4.0.1
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -jar ${agent_opts} -Dskywalking.plugin.mongodb.trace_param=true 
${home}/../libs/mongodb-5.x-scenario.jar &
\ No newline at end of file
diff --git 
a/test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml 
b/test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml
new file mode 100644
index 0000000000..58d2556342
--- /dev/null
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml
@@ -0,0 +1,162 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+segmentItems:
+  - serviceName: mongodb-5.x-scenario
+    segmentSize: ge 2
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: MongoDB/CreateCollectionOperation
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.bind_vars, value: 'testCollection'}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/MixedBulkWriteOperation
+            parentSpanId: 0
+            spanId: 2
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.collection, value: testCollection}
+              - {key: db.bind_vars, value: not null}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/FindOperation
+            parentSpanId: 0
+            spanId: 3
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.collection, value: testCollection}
+              - {key: db.bind_vars, value: '{"name": "org"}'}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/AggregateOperation
+            parentSpanId: 0
+            spanId: 4
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.collection, value: testCollection}
+              - {key: db.bind_vars, value: '{"$match": {"name": "test"}},'}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/MixedBulkWriteOperation
+            parentSpanId: 0
+            spanId: 5
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.collection, value: testCollection}
+              - {key: db.bind_vars, value: '{"name": "org"},'}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/FindOperation
+            parentSpanId: 0
+            spanId: 6
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.collection, value: testCollection}
+              - {key: db.bind_vars, value: '{"name": "testA"}'}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/MixedBulkWriteOperation
+            parentSpanId: 0
+            spanId: 7
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.collection, value: testCollection}
+              - {key: db.bind_vars, value: '{"id": "1"},'}
+            skipAnalysis: 'false'
+          - operationName: MongoDB/DropDatabaseOperation
+            parentSpanId: 0
+            spanId: 8
+            spanLayer: Database
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 42
+            isError: false
+            spanType: Exit
+            peer: mongodb-server:27017
+            tags:
+              - {key: db.type, value: MongoDB}
+              - {key: db.instance, value: test-database}
+              - {key: db.bind_vars, value: null}
+            skipAnalysis: 'false'
+          - operationName: GET:/mongodb-5.x-scenario/case/mongodb-5.x-scenario
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 1
+            isError: false
+            spanType: Entry
+            peer: ''
+            tags:
+              - {key: url, value: 
'http://localhost:8080/mongodb-5.x-scenario/case/mongodb-5.x-scenario'}
+              - {key: http.method, value: GET}
+              - {key: http.status_code, value: '200'}
+            skipAnalysis: 'false'
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list 
b/test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml
similarity index 73%
copy from test/plugin/scenarios/jedis-4.x-scenario/support-version.list
copy to test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml
index 31258966c3..187a8601a7 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml
@@ -14,8 +14,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-4.4.6
-4.3.2
-4.2.3
-4.1.1
-4.0.1
+type: jvm
+entryService: 
http://localhost:8080/mongodb-5.x-scenario/case/mongodb-5.x-scenario
+healthCheck: http://localhost:8080/mongodb-5.x-scenario/case/healthCheck
+startScript: ./bin/startup.sh
+dependencies:
+  mongodb-server:
+    image: mongo:6.0
+    hostname: mongodb-server
diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/pom.xml 
b/test/plugin/scenarios/mongodb-5.x-scenario/pom.xml
new file mode 100644
index 0000000000..9a0985910c
--- /dev/null
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <groupId>org.apache.skywalking.apm.testcase</groupId>
+    <artifactId>mongodb-5.x-scenario</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <compiler.version>1.8</compiler.version>
+        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
+        <test.framework.version>5.2.0</test.framework.version>
+        <spring.boot.version>2.1.6.RELEASE</spring.boot.version>
+        <lombok.version>1.18.20</lombok.version>
+    </properties>
+
+    <name>skywalking-mongodb-5.x-scenario</name>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring.boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.mongodb</groupId>
+                <artifactId>mongodb-driver-core</artifactId>
+                <version>${test.framework.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.mongodb</groupId>
+                <artifactId>mongodb-driver-sync</artifactId>
+                <version>${test.framework.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.mongodb</groupId>
+                <artifactId>bson</artifactId>
+                <version>${test.framework.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongodb-driver-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongodb-driver-sync</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>bson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>mongodb-5.x-scenario</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.boot.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin.version}</version>
+                <configuration>
+                    <source>${compiler.version}</source>
+                    <target>${compiler.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                
<descriptor>src/main/assembly/assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>./target/</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git 
a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000000..ff39fb806e
--- /dev/null
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<assembly
+    
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
 http://maven.apache.org/xsd/assembly-1.1.2.xsd";>
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>./bin</directory>
+            <fileMode>0775</fileMode>
+        </fileSet>
+    </fileSets>
+
+    <files>
+        <file>
+            
<source>${project.build.directory}/mongodb-5.x-scenario.jar</source>
+            <outputDirectory>./libs</outputDirectory>
+            <fileMode>0775</fileMode>
+        </file>
+    </files>
+</assembly>
diff --git 
a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java
 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java
new file mode 100644
index 0000000000..1dd56fec23
--- /dev/null
+++ 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.mongodb;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+    public static void main(String[] args) {
+        try {
+            SpringApplication.run(Application.class, args);
+        } catch (Exception e) {
+            // Never do this
+        }
+    }
+}
diff --git 
a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java
 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java
new file mode 100644
index 0000000000..06a196e216
--- /dev/null
+++ 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.testcase.mongodb.controller;
+
+import com.mongodb.client.AggregateIterable;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.model.Aggregates;
+import com.mongodb.client.model.Filters;
+import org.bson.BsonDocument;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.mongodb.client.model.Filters.eq;
+
+@RestController
+@RequestMapping("/case")
+public class CaseController {
+    
+    @Value(value = "${mongodb.uri}")
+    private String connectionString;
+
+    @GetMapping("/healthCheck")
+    public String health() {
+        // check connect to mongodb server
+        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
+            return "success";
+        }
+    }
+
+    @RequestMapping("/mongodb-5.x-scenario")
+    public String mongoDBCase() {
+        try (MongoClient mongoClient = MongoClients.create(connectionString)) {
+            MongoDatabase db = mongoClient.getDatabase("test-database");
+            // CreateCollectionOperation
+            db.createCollection("testCollection");
+
+            MongoCollection<Document> collection = 
db.getCollection("testCollection");
+            Document document = Document.parse("{id: 1, name: \"test\"}");
+            // MixedBulkWriteOperation
+            collection.insertOne(document);
+
+            // FindOperation
+            FindIterable<Document> findIterable = collection.find(eq("name", 
"org"));
+            findIterable.first();
+
+            // AggregateOperation
+            List<Bson> pipeline = Arrays.asList(
+                    Aggregates.match(Filters.eq("name", "test"))
+            );
+            AggregateIterable<Document> aggregateIterable = 
collection.aggregate(pipeline);
+            aggregateIterable.first();
+
+            // MixedBulkWriteOperation
+            collection.updateOne(eq("name", "org"), BsonDocument.parse("{ $set 
: { \"name\": \"testA\"} }"));
+
+            // FindOperation
+            findIterable = collection.find(eq("name", "testA"));
+            findIterable.first();
+
+            // MixedBulkWriteOperation
+            collection.deleteOne(eq("id", "1"));
+
+            // DropDatabaseOperation
+            mongoClient.getDatabase("test-database").drop();
+        }
+        return "success";
+    }
+}
diff --git 
a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml
 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml
new file mode 100644
index 0000000000..533ff2e37f
--- /dev/null
+++ 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+server:
+  port: 8080
+  servlet:
+    context-path: /mongodb-5.x-scenario
+logging:
+  config: classpath:log4j2.xml
+mongodb:
+  uri: mongodb://mongodb-server/test
\ No newline at end of file
diff --git 
a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml 
b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..9849ed5a8a
--- /dev/null
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<Configuration status="WARN">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_ERR">
+            <PatternLayout charset="UTF-8" pattern="[%d{yyyy-MM-dd 
HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="WARN">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list 
b/test/plugin/scenarios/mongodb-5.x-scenario/support-version.list
similarity index 91%
copy from test/plugin/scenarios/jedis-4.x-scenario/support-version.list
copy to test/plugin/scenarios/mongodb-5.x-scenario/support-version.list
index 31258966c3..89a4430b05 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
+++ b/test/plugin/scenarios/mongodb-5.x-scenario/support-version.list
@@ -14,8 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-4.4.6
-4.3.2
-4.2.3
-4.1.1
-4.0.1
+# MongoDB 5.2+ (MongoClusterImpl replaces MongoClientDelegate)
+5.2.0
+5.5.1

Reply via email to