diff --git a/Jenkinsfile-Agent-Test-2 b/Jenkinsfile-Agent-Test-2
index fd118e659..eb15e93e4 100755
--- a/Jenkinsfile-Agent-Test-2
+++ b/Jenkinsfile-Agent-Test-2
@@ -67,7 +67,7 @@ pipeline {
sh './mvnw -f test/plugin/pom.xml clean package -DskipTests docker:build'
}
}
- stage('Test Cases Report (136)') {
+ stage('Test Cases Report (146)') {
steps {
echo "Test Cases Report"
}
@@ -82,6 +82,12 @@ pipeline {
parallel {
stage('Group1') {
stages {
+ stage('spring-tx 4.x+ (10)') {
+ steps {
+ sh 'bash test/plugin/run.sh spring-tx-scenario'
+ }
+ }
+
stage('spring 4.3.x-5.2.x (54)') {
steps {
sh 'bash test/plugin/run.sh spring-4.3.x-scenario'
diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index 373e9ddb6..6d1eedfee 100755
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -145,4 +145,6 @@ public class ComponentsDefine {
public static final OfficialComponent SOCKET_IO = new OfficialComponent(76, "SocketIO");
public static final OfficialComponent REST_HIGH_LEVEL_CLIENT = new OfficialComponent(77, "rest-high-level-client");
+
+ public static final OfficialComponent SPRING_TX = new OfficialComponent(78, "spring-tx");
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
index 376add85e..89632bd7f 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java
@@ -330,5 +330,13 @@ public class Config {
*/
public static boolean TRACE_HANDLER_CHAIN = false;
}
+
+ public static class SpringTransaction {
+
+ /**
+ * If true, the transaction definition name will be simplified
+ */
+ public static boolean SIMPLIFY_TRANSACTION_DEFINITION_NAME = false;
+ }
}
}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml
index be9d5e161..3284106e1 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml
@@ -30,6 +30,7 @@
spring-annotation-plugin
+ spring-tx-pluginoptional-spring-cloud
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml
new file mode 100644
index 000000000..04b7e9e08
--- /dev/null
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+ optional-spring-plugins
+ org.apache.skywalking
+ 6.6.0-SNAPSHOT
+
+ 4.0.0
+ jar
+
+ apm-spring-tx-plugin
+
+
+ 5.1.2.RELEASE
+
+
+
+
+ org.springframework
+ spring-tx
+ ${spring-tx.version}
+ provided
+
+
+
\ No newline at end of file
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/EndTransactionMethodInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/EndTransactionMethodInterceptor.java
new file mode 100644
index 000000000..f3ea9df55
--- /dev/null
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/EndTransactionMethodInterceptor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.spring.transaction;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+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.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.plugin.spring.transaction.context.Constants;
+import org.springframework.transaction.TransactionStatus;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author zhaoyuguang
+ */
+public class EndTransactionMethodInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ AbstractSpan span = ContextManager.createLocalSpan(Constants.OPERATION_NAME_SPRING_TRANSACTION_PREFIX + method.getName());
+ TransactionStatus status = (TransactionStatus) allArguments[0];
+ span.tag(Constants.TAG_SPRING_TRANSACTION_IS_NEW_TRANSACTION, String.valueOf(status.isNewTransaction()));
+ span.tag(Constants.TAG_SPRING_TRANSACTION_HAS_SAVEPOINT, String.valueOf(status.hasSavepoint()));
+ span.tag(Constants.TAG_SPRING_TRANSACTION_ROLLBACK_ONLY, String.valueOf(status.isRollbackOnly()));
+ span.tag(Constants.TAG_SPRING_TRANSACTION_IS_COMPLETED, String.valueOf(status.isCompleted()));
+ span.setComponent(ComponentsDefine.SPRING_TX);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ ContextManager.stopSpan();
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/GetTransactionMethodInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/GetTransactionMethodInterceptor.java
new file mode 100644
index 000000000..64059b9da
--- /dev/null
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/GetTransactionMethodInterceptor.java
@@ -0,0 +1,81 @@
+/*
+ * 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.spring.transaction;
+
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+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.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.plugin.spring.transaction.context.Constants;
+import org.springframework.transaction.TransactionDefinition;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author zhaoyuguang
+ */
+public class GetTransactionMethodInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ if (allArguments[0] == null) {
+ AbstractSpan span = ContextManager.createLocalSpan(Constants.OPERATION_NAME_SPRING_TRANSACTION_NO_TRANSACTION_DEFINITION_GIVEN);
+ span.setComponent(ComponentsDefine.SPRING_TX);
+ return;
+ }
+ TransactionDefinition definition = (TransactionDefinition) allArguments[0];
+ AbstractSpan span = ContextManager.createLocalSpan(Constants.OPERATION_NAME_SPRING_TRANSACTION_GET_TRANSACTION_METHOD + buildOperationName(definition.getName()));
+ span.tag(Constants.TAG_SPRING_TRANSACTION_ISOLATION_LEVEL, String.valueOf(definition.getIsolationLevel()));
+ span.tag(Constants.TAG_SPRING_TRANSACTION_PROPAGATION_BEHAVIOR, String.valueOf(definition.getPropagationBehavior()));
+ span.tag(Constants.TAG_SPRING_TRANSACTION_TIMEOUT, String.valueOf(definition.getTimeout()));
+ span.setComponent(ComponentsDefine.SPRING_TX);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ ContextManager.stopSpan();
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+
+ private String buildOperationName(String transactionDefinitionName) {
+ if (!Config.Plugin.SpringTransaction.SIMPLIFY_TRANSACTION_DEFINITION_NAME) {
+ return transactionDefinitionName;
+ }
+ String[] ss = transactionDefinitionName.split("\\.");
+
+ int simplifiedLength = ss.length - 2;
+ if (simplifiedLength < 0) {
+ return transactionDefinitionName;
+ }
+ StringBuilder name = new StringBuilder();
+ for (int i = 0; i < ss.length - 1; i++) {
+ name.append(i < simplifiedLength ? ss[i].charAt(0) : ss[i]).append(".");
+ }
+ return name.append(ss[ss.length - 1]).toString();
+ }
+}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/context/Constants.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/context/Constants.java
new file mode 100644
index 000000000..37001362a
--- /dev/null
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/context/Constants.java
@@ -0,0 +1,35 @@
+/*
+ * 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.spring.transaction.context;
+
+/**
+ * @author zhaoyuguang
+ */
+
+public interface Constants {
+ String OPERATION_NAME_SPRING_TRANSACTION_PREFIX = "TX/";
+ String OPERATION_NAME_SPRING_TRANSACTION_GET_TRANSACTION_METHOD = OPERATION_NAME_SPRING_TRANSACTION_PREFIX + "get/";
+ String OPERATION_NAME_SPRING_TRANSACTION_NO_TRANSACTION_DEFINITION_GIVEN = OPERATION_NAME_SPRING_TRANSACTION_GET_TRANSACTION_METHOD + "noTransactionDefinitionGiven";
+ String TAG_SPRING_TRANSACTION_ISOLATION_LEVEL = "isolationLevel";
+ String TAG_SPRING_TRANSACTION_PROPAGATION_BEHAVIOR = "propagationBehavior";
+ String TAG_SPRING_TRANSACTION_TIMEOUT = "timeout";
+ String TAG_SPRING_TRANSACTION_IS_NEW_TRANSACTION = "isNewTransaction";
+ String TAG_SPRING_TRANSACTION_HAS_SAVEPOINT = "hasSavepoint";
+ String TAG_SPRING_TRANSACTION_ROLLBACK_ONLY = "rollbackOnly";
+ String TAG_SPRING_TRANSACTION_IS_COMPLETED = "isCompleted";
+}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/define/AbstractPlatformTransactionManagerInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/define/AbstractPlatformTransactionManagerInstrumentation.java
new file mode 100644
index 000000000..5b1372a47
--- /dev/null
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/define/AbstractPlatformTransactionManagerInstrumentation.java
@@ -0,0 +1,80 @@
+/*
+ * 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.spring.transaction.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.match.NameMatch.byName;
+
+/**
+ * @author zhaoyuguang
+ */
+public class AbstractPlatformTransactionManagerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("getTransaction");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.spring.transaction.GetTransactionMethodInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }, new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("commit").or(named("rollback"));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.spring.transaction.EndTransactionMethodInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ public ClassMatch enhanceClass() {
+ return byName("org.springframework.transaction.support.AbstractPlatformTransactionManager");
+ }
+}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 000000000..2eae69638
--- /dev/null
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,17 @@
+# 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.
+
+spring-tx=org.apache.skywalking.apm.plugin.spring.transaction.define.AbstractPlatformTransactionManagerInstrumentation
diff --git a/docs/en/guides/Plugin-test.md b/docs/en/guides/Plugin-test.md
index 26d9204dd..193cc992c 100644
--- a/docs/en/guides/Plugin-test.md
+++ b/docs/en/guides/Plugin-test.md
@@ -630,9 +630,10 @@ canal 1.0.24-1.1.2 | 5 | 214.05
### Workload 2
-#### Group 1 (2351.54s)
+#### Group 1 (2906.54s)
scenario name | versions | elapsed time (sec)
---|---|---
+spring-tx 4.x+ | 10 | 555.00
spring 4.3.x-5.2.x | 54 | 1769.32
dubbo 2.5.x-2.6.x | 10 | 367.23
dubbo 2.7.x | 4 | 214.99
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index 5db8bc737..b478a2fda 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -109,6 +109,7 @@ property key | Description | Default |
`plugin.solrj.trace_ops_params`|If true, trace all the operation parameters in Solr request, default is false.|`false`|
`plugin.light4j.trace_handler_chain`|If true, trace all middleware/business handlers that are part of the Light4J handler chain for a request.|false|
`plugin.opgroup.*`|Support operation name customize group rules in different plugins. Read [Group rule supported plugins](op_name_group_rule.md)|Not set|
+`plugin.springtransaction.simplify_transaction_definition_name`|If true, the transaction definition name will be simplified.|false|
## Optional Plugins
Java agent plugins are all pluggable. Optional plugins could be provided in `optional-plugins` folder under agent or 3rd party repositories.
@@ -124,6 +125,7 @@ Now, we have the following known optional plugins.
* [Customize enhance](Customize-enhance-trace.md) Trace methods based on description files, rather than write plugin or change source codes.
* Plugin of Spring Cloud Gateway 2.1.x in optional plugin folder. Please only active this plugin when you install agent in Spring Gateway.
* Plugin of [Play Framework](https://www.playframework.com/) 2.6+ (JDK 1.8 required & Scala 2.12/2.13) in optional plugin folder. Please only active this plugin when you install agent in [Play Framework](https://www.playframework.com/).
+* Plugin of Spring Transaction in optional plugin folder. The reason of being optional plugin is, many local span are generated, which also spend more CPU, memory and network.
## Bootstrap class plugins
All bootstrap plugins are optional, due to unexpected risk. Bootstrap plugins are provided in `bootstrap-plugins` folder.
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 7f2be18db..e14c23d3d 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -70,6 +70,7 @@
* Spring Ecosystem
* Spring Bean annotations(@Bean, @Service, @Component, @Repository) 3.x and 4.x (Optional²)
* Spring Core Async SuccessCallback/FailureCallback/ListenableFutureCallback 4.x
+ * Spring Transaction 4.x and 5.x (Optional²)
* [Hystrix: Latency and Fault Tolerance for Distributed Systems](https://github.com/Netflix/Hystrix) 1.4.20 -> 1.5.12
* Scheduler
* [Elastic Job](https://github.com/elasticjob/elastic-job) 2.x
diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml
index 23c7585d6..fe1aa1f62 100755
--- a/oap-server/server-core/src/test/resources/component-libraries.yml
+++ b/oap-server/server-core/src/test/resources/component-libraries.yml
@@ -233,6 +233,9 @@ SocketIO:
rest-high-level-client:
id: 77
languages: Java
+spring-tx:
+ id: 78
+ languages: Java
# .NET/.NET Core components
# [3000, 4000) for C#/.NET only
diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml
index 4087acf4b..1f8f73d84 100755
--- a/oap-server/server-starter/src/main/resources/component-libraries.yml
+++ b/oap-server/server-starter/src/main/resources/component-libraries.yml
@@ -260,6 +260,9 @@ SocketIO:
rest-high-level-client:
id: 77
languages: Java
+spring-tx:
+ id: 78
+ languages: Java
# .NET/.NET Core components
# [3000, 4000) for C#/.NET only
diff --git a/test/plugin/scenarios/spring-tx-scenario/bin/startup.sh b/test/plugin/scenarios/spring-tx-scenario/bin/startup.sh
new file mode 100644
index 000000000..012d0342f
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/bin/startup.sh
@@ -0,0 +1,21 @@
+#!/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
+# 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.
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -Dmysql.servers=${MYSQL_SERVERS} -Dskywalking.plugin.springtransaction.simplify_transaction_definition_name=true -jar ${agent_opts} ${home}/../libs/spring-tx-scenario.jar &
\ No newline at end of file
diff --git a/test/plugin/scenarios/spring-tx-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-tx-scenario/config/expectedData.yaml
new file mode 100644
index 000000000..72cf9955a
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/config/expectedData.yaml
@@ -0,0 +1,168 @@
+# 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.
+
+registryItems:
+ applications:
+ - {spring-tx-scenario: 2}
+ instances:
+ - {spring-tx-scenario: 1}
+ operationNames:
+ - spring-tx-scenario: [Mysql/JDBI/Statement/execute, Mysql/JDBI/Connection/commit,
+ Mysql/JDBI/PreparedStatement/executeUpdate, /case/spring-tx-case, /case/healthCheck,
+ Mysql/JDBI/Connection/close, Mysql/JDBI/Statement/executeQuery]
+ heartbeat: []
+segmentItems:
+ - applicationCode: spring-tx-scenario
+ segmentSize: nq 0
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: TX/get/t.o.a.s.a.t.s.t.s.i.DemoServiceImpl.doBiz
+ operationId: 0
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Unknown
+ startTime: not null
+ endTime: not null
+ componentId: 78
+ componentName: ''
+ isError: false
+ spanType: Local
+ peer: ''
+ peerId: 0
+ tags:
+ - {key: isolationLevel, value: '-1'}
+ - {key: propagationBehavior, value: '0'}
+ - {key: timeout, value: '-1'}
+ - operationName: Mysql/JDBI/PreparedStatement/executeUpdate
+ operationId: 0
+ parentSpanId: 0
+ spanId: 2
+ spanLayer: Database
+ startTime: not null
+ endTime: not null
+ componentId: 33
+ componentName: ''
+ isError: false
+ spanType: Exit
+ peer: mysql:3306
+ peerId: 0
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: ''}
+ - {key: db.statement, value: 'insert into `test`.`table_demo`(name) values(?)'}
+ - operationName: Mysql/JDBI/PreparedStatement/executeUpdate
+ operationId: 0
+ parentSpanId: 0
+ spanId: 3
+ spanLayer: Database
+ startTime: not null
+ endTime: not null
+ componentId: 33
+ componentName: ''
+ isError: false
+ spanType: Exit
+ peer: mysql:3306
+ peerId: 0
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: ''}
+ - {key: db.statement, value: 'insert into `test`.`table_demo`(name) values(?)'}
+ - operationName: Mysql/JDBI/Connection/commit
+ operationId: 0
+ parentSpanId: 4
+ spanId: 5
+ spanLayer: Database
+ startTime: not null
+ endTime: not null
+ componentId: 33
+ componentName: ''
+ isError: false
+ spanType: Exit
+ peer: mysql:3306
+ peerId: 0
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: ''}
+ - {key: db.statement, value: ''}
+ - operationName: Mysql/JDBI/Statement/executeQuery
+ operationId: 0
+ parentSpanId: 4
+ spanId: 6
+ spanLayer: Database
+ startTime: not null
+ endTime: not null
+ componentId: 33
+ componentName: ''
+ isError: false
+ spanType: Exit
+ peer: mysql:3306
+ peerId: 0
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: ''}
+ - {key: db.statement, value: select @@session.tx_read_only}
+ - operationName: Mysql/JDBI/Connection/close
+ operationId: 0
+ parentSpanId: 4
+ spanId: 7
+ spanLayer: Database
+ startTime: not null
+ endTime: not null
+ componentId: 33
+ componentName: ''
+ isError: false
+ spanType: Exit
+ peer: mysql:3306
+ peerId: 0
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: ''}
+ - {key: db.statement, value: ''}
+ - operationName: TX/commit
+ operationId: 0
+ parentSpanId: 0
+ spanId: 4
+ spanLayer: Unknown
+ startTime: not null
+ endTime: not null
+ componentId: 78
+ componentName: ''
+ isError: false
+ spanType: Local
+ peer: ''
+ peerId: 0
+ tags:
+ - {key: isNewTransaction, value: 'true'}
+ - {key: hasSavepoint, value: 'false'}
+ - {key: rollbackOnly, value: 'false'}
+ - {key: isCompleted, value: 'false'}
+ - operationName: /case/spring-tx-case
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: not null
+ endTime: not null
+ componentId: 14
+ componentName: ''
+ isError: false
+ spanType: Entry
+ peer: ''
+ peerId: 0
+ tags:
+ - {key: url, value: 'http://localhost:8080/spring-tx-scenario/case/spring-tx-case'}
+ - {key: http.method, value: GET}
\ No newline at end of file
diff --git a/test/plugin/scenarios/spring-tx-scenario/configuration.yml b/test/plugin/scenarios/spring-tx-scenario/configuration.yml
new file mode 100644
index 000000000..56a0b875e
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/configuration.yml
@@ -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.
+
+type: jvm
+entryService: http://localhost:8080/spring-tx-scenario/case/spring-tx-case
+healthCheck: http://localhost:8080/spring-tx-scenario/case/healthCheck
+startScript: ./bin/startup.sh
+framework: spring-tx
+runningMode: with_optional
+withPlugins: apm-spring-tx-plugin-*.jar
+environment:
+ - MYSQL_SERVERS=mysql:3306
+ - MYSQL_DATABASE=test
+depends_on:
+ - mysql
+dependencies:
+ mysql:
+ image: mysql:5.6
+ hostname: mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD=000000
\ No newline at end of file
diff --git a/test/plugin/scenarios/spring-tx-scenario/pom.xml b/test/plugin/scenarios/spring-tx-scenario/pom.xml
new file mode 100644
index 000000000..b622b1a7a
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/pom.xml
@@ -0,0 +1,109 @@
+
+
+
+ 4.0.0
+
+ org.apache.skywalking
+ spring-tx-scenario
+ 5.0.0
+
+
+ UTF-8
+ 1.8
+ 2.0.0.RELEASE
+ ${test.framework.version}
+
+
+ skywalking-spring-tx-scenario
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${test.framework.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+ ${test.framework.version}
+
+
+ mysql
+ mysql-connector-java
+ 6.0.6
+
+
+
+
+ spring-tx-scenario
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+ maven-compiler-plugin
+
+ ${compiler.version}
+ ${compiler.version}
+ ${project.build.sourceEncoding}
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+ assemble
+ package
+
+ single
+
+
+
+ src/main/assembly/assembly.xml
+
+ ./target/
+
+
+
+
+
+
+
+
+
+ spring-snapshots
+ http://repo.spring.io/snapshot
+
+
+ spring-milestones
+ http://repo.spring.io/milestone
+
+
+
\ No newline at end of file
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/spring-tx-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 000000000..f3feb135a
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ zip
+
+
+
+
+ ./bin
+ 0775
+
+
+
+
+
+ ${project.build.directory}/spring-tx-scenario.jar
+ ./libs
+ 0775
+
+
+
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/Application.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/Application.java
new file mode 100644
index 000000000..406530bcd
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/Application.java
@@ -0,0 +1,35 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * @author zhaoyuguang
+ */
+@SpringBootApplication
+@EnableTransactionManagement
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/config/JdbcConfig.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/config/JdbcConfig.java
new file mode 100644
index 000000000..2f91fc181
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/config/JdbcConfig.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 test.org.apache.skywalking.apm.testcase.spring.transaction.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+import javax.sql.DataSource;
+
+
+/**
+ * @author zhaoyuguang
+ */
+@Configuration
+public class JdbcConfig {
+
+ @Value("${mysql.servers}")
+ private String url;
+
+ @Bean(name = "dataSource")
+ public DataSource createDataSource() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
+ dataSource.setUrl("jdbc:mysql://" + url + "?useSSL=false");
+ dataSource.setUsername("root");
+ dataSource.setPassword("000000");
+ return dataSource;
+ }
+
+ @Bean(name = "jdbcTemplate")
+ public JdbcTemplate createJdbcTemplate(DataSource dataSource) {
+ return new JdbcTemplate(dataSource);
+ }
+
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/config/TransactionConfig.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/config/TransactionConfig.java
new file mode 100644
index 000000000..cbd421fe4
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/config/TransactionConfig.java
@@ -0,0 +1,38 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import javax.sql.DataSource;
+
+/**
+ * @author zhaoyuguang
+ */
+@Configuration
+public class TransactionConfig {
+
+ @Bean
+ public PlatformTransactionManager transactionManager(DataSource dataSource){
+ return new DataSourceTransactionManager(dataSource);
+ }
+
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/controller/CaseController.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/controller/CaseController.java
new file mode 100644
index 000000000..92d652462
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/controller/CaseController.java
@@ -0,0 +1,72 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import test.org.apache.skywalking.apm.testcase.spring.transaction.service.DemoService;
+
+/**
+ * @author zhaoyuguang
+ */
+@Controller
+@RequestMapping("/case")
+@PropertySource("classpath:application.properties")
+public class CaseController {
+
+ @Value("${mysql.servers}")
+ private String address;
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+ @Autowired
+ private DemoService demoService;
+
+
+ @RequestMapping("/spring-tx-case")
+ @ResponseBody
+ public String springTransactionCase() {
+ demoService.doBiz();
+ return "Success";
+ }
+
+ @RequestMapping("/healthCheck")
+ @ResponseBody
+ public String healthCheck() {
+ try {
+ jdbcTemplate.execute("create database if not exists test default charset = utf8");
+ jdbcTemplate.execute("" +
+ "CREATE TABLE IF NOT EXISTS `test`.`table_demo` (\n" +
+ " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" +
+ " `name` varchar(60),\n" +
+ " PRIMARY KEY (`id`)\n" +
+ ") ENGINE=InnoDB");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ return "success";
+ }
+
+}
+
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/dao/DemoDao.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/dao/DemoDao.java
new file mode 100644
index 000000000..7d5459eea
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/dao/DemoDao.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction.dao;
+
+/**
+ * @author zhaoyuguang
+ */
+
+public interface DemoDao {
+
+ int insert(String name);
+
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/dao/impl/DemoDaoImpl.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/dao/impl/DemoDaoImpl.java
new file mode 100644
index 000000000..806ebc9c5
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/dao/impl/DemoDaoImpl.java
@@ -0,0 +1,39 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction.dao.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import test.org.apache.skywalking.apm.testcase.spring.transaction.dao.DemoDao;
+
+/**
+ * @author zhaoyuguang
+ */
+@Repository
+public class DemoDaoImpl implements DemoDao {
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+ @Override
+ public int insert(String name) {
+ return jdbcTemplate.update("insert into `test`.`table_demo`(name) values(?)", name);
+ }
+
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/service/DemoService.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/service/DemoService.java
new file mode 100644
index 000000000..a4ad4eb16
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/service/DemoService.java
@@ -0,0 +1,28 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction.service;
+
+/**
+ * @author zhaoyuguang
+ */
+
+public interface DemoService {
+
+ void doBiz();
+
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/service/impl/DemoServiceImpl.java b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/service/impl/DemoServiceImpl.java
new file mode 100644
index 000000000..19b42868c
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/spring/transaction/service/impl/DemoServiceImpl.java
@@ -0,0 +1,41 @@
+/*
+ * 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 test.org.apache.skywalking.apm.testcase.spring.transaction.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import test.org.apache.skywalking.apm.testcase.spring.transaction.dao.DemoDao;
+import test.org.apache.skywalking.apm.testcase.spring.transaction.service.DemoService;
+
+/**
+ * @author zhaoyuguang
+ */
+@Service
+public class DemoServiceImpl implements DemoService {
+
+ @Autowired
+ private DemoDao demoDao;
+
+ @Override
+ @Transactional
+ public void doBiz() {
+ demoDao.insert("1");
+ demoDao.insert("2");
+ }
+}
diff --git a/test/plugin/scenarios/spring-tx-scenario/src/main/resources/application.properties b/test/plugin/scenarios/spring-tx-scenario/src/main/resources/application.properties
new file mode 100644
index 000000000..e9aaf725e
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/src/main/resources/application.properties
@@ -0,0 +1,21 @@
+#
+# 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
+server.contextPath=/spring-tx-scenario
+server.servlet.contextPath=/spring-tx-scenario
\ No newline at end of file
diff --git a/test/plugin/scenarios/spring-tx-scenario/support-version.list b/test/plugin/scenarios/spring-tx-scenario/support-version.list
new file mode 100644
index 000000000..4045a35ca
--- /dev/null
+++ b/test/plugin/scenarios/spring-tx-scenario/support-version.list
@@ -0,0 +1,26 @@
+# 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
+# "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.
+
+2.1.9.RELEASE
+2.1.5.RELEASE
+2.1.0.RELEASE
+2.0.9.RELEASE
+2.0.5.RELEASE
+2.0.0.RELEASE
+1.5.22.RELEASE
+1.5.11.RELEASE
+1.5.0.RELEASE
+1.4.7.RELEASE
\ No newline at end of file