diff --git a/.gitignore b/.gitignore
index e4c325744c2eaa45f3f8cc885b41e5a15adcbacf..e34b7b267cd5f0f3f6bcec4a544be0f55896447b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,13 +28,12 @@ target/
 /distribution/bin
 /distribution/conf
 /distribution/lib
-server/*root.*
-server/.root.*
-*.data
+/server/*root.*
+/server/.root.*
+/server/sessionStore/
+/sessionStore/
 
 # system ignore
 .DS_Store
 Thumbs.db
-*.orig
-*.class
-data*
+*.orig
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 8e8ed7ff9d1f1d93709317bfba256c0cbc48cd41..62273ae12631e120f3134378f20a18a0466f48be 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,6 +2,7 @@ language: java
 sudo: false # faster builds
 
 jdk:
+  - openjdk11
   - openjdk8
 
 cache:
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 065f1ec491adea9fd6dca4bfa35e4a8d24990baf..fb337ba0b69c37b014452d6175750a0cd69b481e 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
 ## Enforcement
 
 Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at dev.fescar@gmail.com. All
+reported by contacting the project team at dev-seata@googlegroups.com. All
 complaints will be reviewed and investigated and will result in a response that
 is deemed necessary and appropriate to the circumstances. The project team is
 obligated to maintain confidentiality with regard to the reporter of an incident.
diff --git a/README.md b/README.md
index d6fd9a6204731683eb72bb223acac5d8e45bc138..a4676b789b661abd4042e378ad139435b2fcc6db 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,7 @@
 [![codecov](https://codecov.io/gh/seata/seata/branch/develop/graph/badge.svg)](https://codecov.io/gh/seata/seata)
 [![license](https://img.shields.io/github/license/seata/seata.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
 [![maven](https://img.shields.io/maven-central/v/io.seata/seata-parent.svg)](https://search.maven.org/search?q=io.seata)
+[![](https://img.shields.io/twitter/follow/seataio.svg?label=Follow&style=social&logoWidth=0)](https://twitter.com/intent/follow?screen_name=seataio)
 
 ## What is Seata?
 
@@ -80,7 +81,7 @@ For more details about principle and design, please go to [Seata wiki page](http
 
 ## Maven dependency
 ```xml
-<seata.version>0.5.0</seata.version>
+<seata.version>0.5.1</seata.version>
 
 <dependency>
     <groupId>io.seata</groupId>
@@ -126,7 +127,7 @@ Contributors are welcomed to join the FEATS project. Please check [CONTRIBUTING]
 * [Twitter](https://twitter.com/seataio): Follow along for latest Seata news on Twitter.
 
 * Mailing list: 
-  * dev-fescar@googlegroups.com , for dev/user discussion. [subscribe](mailto:dev-fescar+subscribe@googlegroups.com), [unsubscribe](mailto:dev-fescar+unsubscribe@googlegroups.com), [archive](https://groups.google.com/forum/#!forum/dev-fescar)
+  * dev-seata@googlegroups.com , for dev/user discussion. [subscribe](mailto:dev-seata+subscribe@googlegroups.com), [unsubscribe](mailto:dev-seata+unsubscribe@googlegroups.com), [archive](https://groups.google.com/forum/#!forum/dev-seata)
   
 **Dingtalk**
 
diff --git a/all/pom.xml b/all/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8f092f4971df482b34d259b9ce14998a4336f3db
--- /dev/null
+++ b/all/pom.xml
@@ -0,0 +1,562 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 1999-2019 Seata.io Group.
+  ~
+  ~  Licensed 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>
+
+    <groupId>io.seata</groupId>
+    <artifactId>seata-all</artifactId>
+    <version>0.5.2</version>
+
+    <name>Seata All-in-one ${project.version}</name>
+    <url>http://seata.io</url>
+    <description>Seata is an easy-to-use, high-performance, java based, open source distributed transaction solution.
+    </description>
+    <prerequisites>
+        <maven>3.6.0</maven>
+    </prerequisites>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+    <developers>
+        <developer>
+            <id>Seata</id>
+            <name>Seata</name>
+            <url>http://seata.io</url>
+        </developer>
+    </developers>
+
+    <organization>
+        <name>Seata</name>
+        <url>https://github.com/seata</url>
+    </organization>
+
+    <issueManagement>
+        <system>github</system>
+        <url>https://github.com/seata/seata/issues</url>
+    </issueManagement>
+
+    <scm>
+        <url>git@github.com:seata/seata.git</url>
+        <connection>scm:git@github.com:seata/seata.git</connection>
+        <developerConnection>scm:git@github.com:seata/seata.git</developerConnection>
+    </scm>
+
+    <properties>
+        <!-- Compiler settings properties -->
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.seata</groupId>
+                <artifactId>seata-bom</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <!-- seata projects -->
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-config-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-config-apollo</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-config-nacos</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-config-zk</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-config-consul</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-consul</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-eureka</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-nacos</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-redis</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-sofa</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-zk</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-discovery-etcd3</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-dubbo</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-dubbo-alibaba</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-sofa-rpc</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-rm</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-rm-datasource</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-spring</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-tcc</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-tm</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- spring  -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+        </dependency>
+
+        <!-- the 3rd part -->
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.typesafe</groupId>
+            <artifactId>config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-pool</groupId>
+            <artifactId>commons-pool</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>aopalliance</groupId>
+            <artifactId>aopalliance</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.101tec</groupId>
+            <artifactId>zkclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>registry-client-all</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.spring</groupId>
+            <artifactId>spring-context-support</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.nacos</groupId>
+            <artifactId>nacos-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ctrip.framework.apollo</groupId>
+            <artifactId>apollo-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.netflix.eureka</groupId>
+            <artifactId>eureka-client</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.netflix.archaius</groupId>
+            <artifactId>archaius-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ecwid.consul</groupId>
+            <artifactId>consul-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.etcd</groupId>
+            <artifactId>jetcd-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>sofa-rpc-all</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <extensions>
+            <extension>
+                <groupId>kr.motd.maven</groupId>
+                <artifactId>os-maven-plugin</artifactId>
+                <version>1.5.0.Final</version>
+            </extension>
+        </extensions>
+        <resources>
+            <resource>
+                <directory>${user.dir}</directory>
+                <includes>
+                    <include>LICENSE</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.0.2</version>
+                <configuration>
+                    <archive>
+                        <addMavenDescriptor>true</addMavenDescriptor>
+                        <index>true</index>
+                        <manifest>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                        </manifest>
+                        <manifestEntries>
+                            <Implementation-Build>${maven.build.timestamp}</Implementation-Build>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.5.1</version>
+                <configuration>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.5</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.4.3</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <createSourcesJar>true</createSourcesJar>
+                            <promoteTransitiveDependencies>false</promoteTransitiveDependencies>
+                            <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
+                            <createDependencyReducedPom>false</createDependencyReducedPom>
+                            <artifactSet>
+                                <includes>
+                                    <include>io.seata:seata-common</include>
+                                    <include>io.seata:seata-core</include>
+                                    <include>io.seata:seata-config-core</include>
+                                    <include>io.seata:seata-config-apollo</include>
+                                    <include>io.seata:seata-config-nacos</include>
+                                    <include>io.seata:seata-config-zk</include>
+                                    <include>io.seata:seata-config-consul</include>
+                                    <include>io.seata:seata-discovery-core</include>
+                                    <include>io.seata:seata-discovery-consul</include>
+                                    <include>io.seata:seata-discovery-eureka</include>
+                                    <include>io.seata:seata-discovery-nacos</include>
+                                    <include>io.seata:seata-discovery-redis</include>
+                                    <include>io.seata:seata-discovery-sofa</include>
+                                    <include>io.seata:seata-discovery-zk</include>
+                                    <include>io.seata:seata-discovery-etcd3</include>
+                                    <include>io.seata:seata-dubbo</include>
+                                    <include>io.seata:seata-dubbo-alibaba</include>
+                                    <include>io.seata:seata-rm</include>
+                                    <include>io.seata:seata-rm-datasource</include>
+                                    <include>io.seata:seata-sofa-rpc</include>
+                                    <include>io.seata:seata-spring</include>
+                                    <include>io.seata:seata-tcc</include>
+                                    <include>io.seata:seata-tm</include>
+                                </includes>
+                            </artifactSet>
+                            <transformers>
+                                <!-- META-INF/services -->
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                                <!-- spring相关 -->
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>META-INF/spring.handlers</resource>
+                                </transformer>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>META-INF/spring.schemas</resource>
+                                </transformer>
+                            </transformers>
+                            <filters>
+                                <filter>
+                                    <artifact>*:*</artifact>
+                                    <excludes>
+                                        <exclude>file.conf</exclude>
+                                        <exclude>registry.conf</exclude>
+                                    </excludes>
+                                </filter>
+                            </filters>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.0.2</version>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <version>2.10.4</version>
+                        <configuration>
+                            <encoding>${project.build.sourceEncoding}</encoding>
+                            <detectOfflineLinks>true</detectOfflineLinks>
+                            <breakiterator>true</breakiterator>
+                            <author>false</author>
+                            <keywords>true</keywords>
+                            <quiet>true</quiet>
+                            <includeDependencySources>true</includeDependencySources>
+                            <dependencySourceIncludes>
+                                <dependencySourceInclude>io.seata:seata-*</dependencySourceInclude>
+                            </dependencySourceIncludes>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <id>attach-javadocs</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.sonatype.plugins</groupId>
+                        <artifactId>nexus-staging-maven-plugin</artifactId>
+                        <version>1.6.7</version>
+                        <extensions>true</extensions>
+                        <configuration>
+                            <serverId>oss_seata</serverId>
+                            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+                            <autoReleaseAfterClose>false</autoReleaseAfterClose>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <version>1.6</version>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                                <configuration>
+                                    <keyname>F72AF874ECA9BBA7751C2DFD553EBAF7AC17F320</keyname>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+            <distributionManagement>
+                <snapshotRepository>
+                    <id>oss_seata</id>
+                    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+                </snapshotRepository>
+                <repository>
+                    <id>oss_seata</id>
+                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+                </repository>
+            </distributionManagement>
+        </profile>
+    </profiles>
+</project>
diff --git a/bom/pom.xml b/bom/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dc5ca5ed57d17aeb4a6dc867a52838db9739f390
--- /dev/null
+++ b/bom/pom.xml
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 1999-2019 Seata.io Group.
+  ~
+  ~  Licensed 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>io.seata</groupId>
+    <artifactId>seata-bom</artifactId>
+    <version>0.5.2</version>
+
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>pom</packaging>
+
+    <name>Seata bom ${project.version}</name>
+
+    <properties>
+        <spring.version>4.3.23.RELEASE</spring.version>
+        <netty4.version>4.1.24.Final</netty4.version>
+        <junit.version>4.12</junit.version>
+        <dubbo.version>2.7.0</dubbo.version>
+        <dubbo.alibaba.version>2.6.5</dubbo.alibaba.version>
+        <sofa.rpc.version>5.5.3</sofa.rpc.version>
+        <fastjson.version>1.2.48</fastjson.version>
+        <config.version>1.2.1</config.version>
+        <slf4j-api.version>1.7.22</slf4j-api.version>
+        <logback-classic.version>1.2.0</logback-classic.version>
+        <commons-lang.version>2.6</commons-lang.version>
+        <commons-pool2.version>2.4.2</commons-pool2.version>
+        <commons-pool.version>1.6</commons-pool.version>
+        <cglib.version>3.1</cglib.version>
+        <aopalliance.version>1.0</aopalliance.version>
+        <zkclient.version>0.10</zkclient.version>
+        <curator-test.version>2.9.1</curator-test.version>
+        <spring-context-support.version>1.0.2</spring-context-support.version>
+        <testng.version>6.4</testng.version>
+        <jacoco-maven-plugin.version>0.8.3</jacoco-maven-plugin.version>
+        <apollo-client.version>1.1.0</apollo-client.version>
+        <redis-clients.version>2.9.0</redis-clients.version>
+        <eureka-clients.version>1.9.5</eureka-clients.version>
+        <consul-clients.version>1.4.2</consul-clients.version>
+        <nacos-client.version>0.9.1</nacos-client.version>
+        <etcd-client-v3.version>0.3.0</etcd-client-v3.version>
+        <testcontainers.version>1.11.2</testcontainers.version>
+        <guava.version>27.0.1-jre</guava.version>
+        <javax-inject.version>1</javax-inject.version>
+        <archaius-core.version>0.7.6</archaius-core.version>
+        <sofa.registry.version>5.2.0</sofa.registry.version>
+        <httpclient.version>4.5.8</httpclient.version>
+        <httpcore.version>4.4.11</httpcore.version>
+        <druid.version>1.1.12</druid.version>
+        <caffeine.version>2.7.0</caffeine.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <!-- spring  -->
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-framework-bom</artifactId>
+                <version>${spring.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <!-- the 3rd part -->
+            <dependency>
+                <groupId>io.netty</groupId>
+                <artifactId>netty-all</artifactId>
+                <version>${netty4.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>fastjson</artifactId>
+                <version>${fastjson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>druid</artifactId>
+                <version>${druid.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alipay.sofa</groupId>
+                <artifactId>sofa-rpc-all</artifactId>
+                <version>${sofa.rpc.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.typesafe</groupId>
+                <artifactId>config</artifactId>
+                <version>${config.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j-api.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-classic</artifactId>
+                <version>${logback-classic.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-lang</groupId>
+                <artifactId>commons-lang</artifactId>
+                <version>${commons-lang.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-pool2</artifactId>
+                <version>${commons-pool2.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-pool</groupId>
+                <artifactId>commons-pool</artifactId>
+                <version>${commons-pool.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.dubbo</groupId>
+                <artifactId>dubbo</artifactId>
+                <version>${dubbo.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba</groupId>
+                <artifactId>dubbo</artifactId>
+                <version>${dubbo.alibaba.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>cglib</groupId>
+                <artifactId>cglib</artifactId>
+                <version>${cglib.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>aopalliance</groupId>
+                <artifactId>aopalliance</artifactId>
+                <version>${aopalliance.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.101tec</groupId>
+                <artifactId>zkclient</artifactId>
+                <version>${zkclient.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <artifactId>slf4j-log4j12</artifactId>
+                        <groupId>org.slf4j</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>io.netty</artifactId>
+                        <groupId>netty</groupId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.curator</groupId>
+                <artifactId>curator-test</artifactId>
+                <version>${curator-test.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alipay.sofa</groupId>
+                <artifactId>registry-client-all</artifactId>
+                <version>${sofa.registry.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alipay.sofa</groupId>
+                <artifactId>registry-test</artifactId>
+                <version>${sofa.registry.version}</version>
+                <exclusions>
+                    <exclusion>
+                        <artifactId>log4j-over-slf4j</artifactId>
+                        <groupId>org.slf4j</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>log4j-jcl</artifactId>
+                        <groupId>org.apache.logging.log4j</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>log4j-core</artifactId>
+                        <groupId>org.apache.logging.log4j</groupId>
+                    </exclusion>
+                    <exclusion>
+                        <artifactId>log4j-api</artifactId>
+                        <groupId>org.apache.logging.log4j</groupId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba.spring</groupId>
+                <artifactId>spring-context-support</artifactId>
+                <version>${spring-context-support.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.alibaba.nacos</groupId>
+                <artifactId>nacos-client</artifactId>
+                <version>${nacos-client.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.ctrip.framework.apollo</groupId>
+                <artifactId>apollo-client</artifactId>
+                <version>${apollo-client.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>redis.clients</groupId>
+                <artifactId>jedis</artifactId>
+                <version>${redis-clients.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.netflix.eureka</groupId>
+                <artifactId>eureka-client</artifactId>
+                <version>${eureka-clients.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.netflix.archaius</groupId>
+                <artifactId>archaius-core</artifactId>
+                <version>${archaius-core.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.ecwid.consul</groupId>
+                <artifactId>consul-api</artifactId>
+                <version>${consul-clients.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.etcd</groupId>
+                <artifactId>jetcd-core</artifactId>
+                <version>${etcd-client-v3.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>io.etcd</groupId>
+                <artifactId>jetcd-launcher</artifactId>
+                <version>${etcd-client-v3.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.testcontainers</groupId>
+                <artifactId>testcontainers</artifactId>
+                <version>${testcontainers.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.inject</groupId>
+                <artifactId>javax.inject</artifactId>
+                <version>${javax-inject.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpclient</artifactId>
+                <version>${httpclient.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.httpcomponents</groupId>
+                <artifactId>httpcore</artifactId>
+                <version>${httpcore.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.github.ben-manes.caffeine</groupId>
+                <artifactId>caffeine</artifactId>
+                <version>${caffeine.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <profiles>
+        <profile>
+            <id>release</id>
+            <build>
+                <plugins>
+                    <!-- GPG -->
+                    <plugin>
+                        <groupId>org.sonatype.plugins</groupId>
+                        <artifactId>nexus-staging-maven-plugin</artifactId>
+                        <version>1.6.7</version>
+                        <extensions>true</extensions>
+                        <configuration>
+                            <serverId>oss_seata</serverId>
+                            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+                            <autoReleaseAfterClose>false</autoReleaseAfterClose>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <version>1.6</version>
+                        <executions>
+                            <execution>
+                                <id>sign-artifacts</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                                <configuration>
+                                    <keyname>F72AF874ECA9BBA7751C2DFD553EBAF7AC17F320</keyname>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+
+            <distributionManagement>
+                <snapshotRepository>
+                    <id>oss_seata</id>
+                    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+                </snapshotRepository>
+                <repository>
+                    <id>oss_seata</id>
+                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+                </repository>
+            </distributionManagement>
+
+        </profile>
+    </profiles>
+
+</project>
\ No newline at end of file
diff --git a/common/pom.xml b/common/pom.xml
index f591853610dbb224e3137cfcd5955e4092f97214..d3986b408f7556ebe327ceb2d3c5c82127f0d871 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -38,7 +38,6 @@
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <optional>true</optional>
         </dependency>
         <dependency>
             <groupId>commons-lang</groupId>
@@ -48,10 +47,5 @@
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
         </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 </project>
diff --git a/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java b/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java
index f78ecfca064a46e3c82c0a244b7f1611e6b812e2..80af780441fb7e819a1dc9cc42813b081bc1926f 100644
--- a/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java
+++ b/common/src/main/java/io/seata/common/exception/FrameworkErrorCode.java
@@ -23,88 +23,99 @@ package io.seata.common.exception;
  */
 public enum FrameworkErrorCode {
     /**
-     * 0001 ~ 0099  与配置相关的错误
+     * 0001 ~ 0099  Configuration related errors
      */
-    ThreadPoolFull("0004", "netty线程池满", "请在配置文件中调整线程数, corePoolSize 的值调大一些"),
+    ThreadPoolFull("0004", "Thread pool is full", "Please check the thread pool configuration"),
+
     /**
      * The Init services client error.
      */
-    InitSeataClientError("0008", "seataAppName or seataServerGroup is null", ""),
+    InitSeataClientError("0008", "Seata app name or seata server group is null", "Please check your configuration"),
+
     /**
      * The Null rule error.
      */
-    NullRuleError("0010", "services rules is null", ""),
+    NullRuleError("0010", "Services rules is null", "Please check your configuration"),
 
     /**
-     * 0101 ~ 0199 网络有关的错误,连接不上,断开,dispatch等
+     * 0101 ~ 0199 Network related error. (Not connected, disconnected, dispatched, etc.)
      */
-    NetConnect("0101", "无法连接服务器", "请检查seata server是否启动,到seata server的网络连接是否正常"),
+    NetConnect("0101", "Can not connect to the server", "Please check if the seata service is started. Is the network connection to the seata server normal?"),
+
     /**
      * The Net reg appname.
      */
-    NetRegAppname("0102", "register client app name failed", "请检查seata server是否启动,到seata server的网络连接是否正常"),
+    NetRegAppname("0102", "Register client app name failed", "Please check if the seata service is started. Is the network connection to the seata server normal?"),
+
     /**
      * The Net disconnect.
      */
-    NetDisconnect("0103", "seataConnection closed", "网络断开,请检查到对端(client 或seata server)的网络连接"),
+    NetDisconnect("0103", "Seata connection closed", "The network is disconnected. Please check the network connection to the client or seata server."),
+
     /**
      * The Net dispatch.
      */
-    NetDispatch("0104", "dispatch 错误", "网络处理错误,请检查到对端(client 或seata server)的网络连接 "),
+    NetDispatch("0104", "Dispatch error", "Network processing error. Please check the network connection to the client or seata server."),
+
     /**
      * The Net on message.
      */
-    NetOnMessage("0105", "on message 错误", "网络处理错误,请检查到对端(client 或seata server)的网络连接 "),
+    NetOnMessage("0105", "On message error", "Network processing error. Please check the network connection to the client or seata server."),
     /**
      * Get channel error framework error code.
      */
-    getChannelError("0106", "getChannelError", "getChannelError"),
+    getChannelError("0106", "Get channel error", "Get channel error"),
+
     /**
      * Channel not writable framework error code.
      */
-    ChannelNotWritable("0107", "ChannelNotWritable", "ChannelNotWritable"),
+    ChannelNotWritable("0107", "Channel not writable", "Channel not writable"),
+
     /**
      * Send half message failed framework error code.
      */
-    SendHalfMessageFailed("0108", "SendHalfMessageFailed", "SendHalfMessageFailed"),
+    SendHalfMessageFailed("0108", "Send half message failed", "Send half message failed"),
 
     /**
      * Channel is not writable framework error code.
      */
-    ChannelIsNotWritable("0109", "ChannelIsNotWritable", "ChannelIsNotWritable"),
+    ChannelIsNotWritable("0109", "Channel is not writable", "Channel is not writable"),
     /**
      * No available service framework error code.
      */
-    NoAvailableService("0110", "NoAvailableService", "NoAvailableService"),
+    NoAvailableService("0110", "No available service", "No available service"),
 
     /**
      * Invalid configuration framework error code.
      */
-    InvalidConfiguration("0201", "InvalidConfiguration", "InvalidConfiguration"),
+    InvalidConfiguration("0201", "Invalid configuration", "Invalid configuration"),
 
     /**
      * Exception caught framework error code.
      */
-    ExceptionCaught("0318", "异常", ""),
+    ExceptionCaught("0318", "Exception caught", "Exception caught"),
+
     /**
-     * Regist rm framework error code.
+     * Register rm framework error code.
      */
-    RegistRM("0304", "注册RM失败", ""),
+    RegisterRM("0304", "Register RM failed", "Register RM failed"),
 
     /**
-     * 未定义错误
+     * Undefined error
      */
-    UnknownAppError("10000", "unknown error", "内部错误"),
+    UnknownAppError("10000", "Unknown error", "Internal error"),
     ;
 
     /**
      * The Err code.
      */
     private String errCode;
+
     /**
      * The Err message.
      */
     private String errMessage;
+
     /**
      * The Err dispose.
      */
diff --git a/common/src/main/java/io/seata/common/util/CollectionUtils.java b/common/src/main/java/io/seata/common/util/CollectionUtils.java
index 1ad659d8b9e5a565a10af136d8836007896bba0e..76126fc4cf4d51da9d26ebdcad2914519a906a7c 100644
--- a/common/src/main/java/io/seata/common/util/CollectionUtils.java
+++ b/common/src/main/java/io/seata/common/util/CollectionUtils.java
@@ -21,6 +21,7 @@ import java.util.Collection;
  * The type Collection utils.
  *
  * @author zhangsen
+ * @author Geng Zhang
  */
 public class CollectionUtils {
 
@@ -43,4 +44,23 @@ public class CollectionUtils {
     public static boolean isNotEmpty(Collection col){
         return col != null && col.size() > 0;
     }
+
+    /**
+     * Is size equals boolean.
+     *
+     * @param col0 the col 0
+     * @param col1 the col 1
+     * @return the boolean
+     */
+    public static boolean isSizeEquals(Collection col0, Collection col1) {
+        if (col0 == null) {
+            return col1 == null;
+        } else {
+            if (col1 == null) {
+                return false;
+            } else {
+                return col0.size() == col1.size();
+            }
+        }
+    }
 }
diff --git a/common/src/main/java/io/seata/common/util/StringUtils.java b/common/src/main/java/io/seata/common/util/StringUtils.java
index db98e470ac3cfb1b24886b0601ed7f13c14ba768..217538aae17674ca53488f42b9a03268df82745f 100644
--- a/common/src/main/java/io/seata/common/util/StringUtils.java
+++ b/common/src/main/java/io/seata/common/util/StringUtils.java
@@ -32,6 +32,7 @@ import javax.sql.rowset.serial.SerialBlob;
  * The type String utils.
  *
  * @author jimin.jm @alibaba-inc.com
+ * @author Geng Zhang
  */
 public class StringUtils {
 
@@ -45,7 +46,7 @@ public class StringUtils {
      * @param str the str
      * @return the boolean
      */
-    public static final boolean isNullOrEmpty(String str) {
+    public static boolean isNullOrEmpty(String str) {
         return (str == null) || (str.isEmpty());
     }
 
@@ -196,4 +197,32 @@ public class StringUtils {
         }
         return sb.toString();
     }
+
+    /**
+     * Equals boolean.
+     *
+     * @param a the a
+     * @param b the b
+     * @return boolean
+     */
+    public static boolean equals(String a, String b) {
+        if (a == null) {
+            return b == null;
+        }
+        return a.equals(b);
+    }
+
+    /**
+     * Equals ignore case boolean.
+     *
+     * @param a the a
+     * @param b the b
+     * @return the boolean
+     */
+    public static boolean equalsIgnoreCase(String a, String b) {
+        if (a == null) {
+            return b == null;
+        }
+        return a.equalsIgnoreCase(b);
+    }
 }
diff --git a/common/src/test/java/io/seata/common/XIDTest.java b/common/src/test/java/io/seata/common/XIDTest.java
index 04f558422888231bca287ce1e9bf0e6200fc2354..9d35fdecd791a0d03c65c6a82b287aaee7649769 100644
--- a/common/src/test/java/io/seata/common/XIDTest.java
+++ b/common/src/test/java/io/seata/common/XIDTest.java
@@ -17,7 +17,7 @@ package io.seata.common;
 
 import java.util.Random;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java b/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java
index 9e9e9c3cc758118f15b64f2d0af8a94a46f524f6..0e1f8ba7f04ebbc24c03be9a3b46c4f3939b4c8e 100644
--- a/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java
+++ b/common/src/test/java/io/seata/common/exception/FrameworkExceptionTest.java
@@ -17,7 +17,7 @@ package io.seata.common.exception;
 
 import java.sql.SQLException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -154,4 +154,4 @@ public class FrameworkExceptionTest {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/common/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java b/common/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java
index a3761da5f3fc59786f8ee69d5960313c236e7e9e..23b4e3fa2341dd09d13edb44f1655c5e387e9f4e 100644
--- a/common/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java
+++ b/common/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java
@@ -15,10 +15,10 @@
  */
 package io.seata.common.loader;
 
-import java.util.List;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
-import org.junit.Assert;
-import org.junit.Test;
+import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -36,15 +36,17 @@ public class EnhancedServiceLoaderTest {
     @Test
     public void testLoadByClassAndClassLoader() {
         Hello load = EnhancedServiceLoader.load(Hello.class, Hello.class.getClassLoader());
-        Assert.assertEquals(load.say(), "Bonjour");
+        Assertions.assertEquals(load.say(), "Bonjour");
     }
 
     /**
      * Test load exception.
      */
-    @Test(expected = EnhancedServiceNotFoundException.class)
+    @Test
     public void testLoadException() {
-        EnhancedServiceLoaderTest load = EnhancedServiceLoader.load(EnhancedServiceLoaderTest.class);
+        Assertions.assertThrows(EnhancedServiceNotFoundException.class, () -> {
+            EnhancedServiceLoaderTest load = EnhancedServiceLoader.load(EnhancedServiceLoaderTest.class);
+        });
     }
 
     /**
@@ -71,7 +73,7 @@ public class EnhancedServiceLoaderTest {
     @Test
     public void testLoadByClassAndClassLoaderAndActivateName() {
         Hello englishHello = EnhancedServiceLoader
-            .load(Hello.class, "EnglishHello", EnhancedServiceLoaderTest.class.getClassLoader());
+                .load(Hello.class, "EnglishHello", EnhancedServiceLoaderTest.class.getClassLoader());
         assertThat(englishHello.say()).isEqualTo("hello!");
     }
 
@@ -93,8 +95,8 @@ public class EnhancedServiceLoaderTest {
     @Test
     public void getAllExtensionClass1() {
         List<Class> allExtensionClass = EnhancedServiceLoader
-            .getAllExtensionClass(Hello.class, ClassLoader.getSystemClassLoader());
+                .getAllExtensionClass(Hello.class, ClassLoader.getSystemClassLoader());
         assertThat(allExtensionClass).isNotEmpty();
     }
 
-}
\ No newline at end of file
+}
diff --git a/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java b/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java
index 046a2492c24b86caa3f90bf81f4a39ff797d71e2..e344e2878eb963b5cccd61fdd3d21d33b63fb96c 100644
--- a/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java
+++ b/common/src/test/java/io/seata/common/thread/NamedThreadFactoryTest.java
@@ -18,7 +18,7 @@ package io.seata.common.thread;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author Otis.z
@@ -41,4 +41,4 @@ public class NamedThreadFactoryTest {
         assertThat(testNameThread.getName()).startsWith("testNameThread");
         assertThat(testNameThread.isDaemon()).isTrue();
     }
-}
\ No newline at end of file
+}
diff --git a/common/src/test/java/io/seata/common/thread/RejectedPoliciesTest.java b/common/src/test/java/io/seata/common/thread/RejectedPoliciesTest.java
index f84e7a6ba478635d71fe221fb04e345151a438d3..0bd6ca026dd32d8238de2a03956e73c129b34f80 100644
--- a/common/src/test/java/io/seata/common/thread/RejectedPoliciesTest.java
+++ b/common/src/test/java/io/seata/common/thread/RejectedPoliciesTest.java
@@ -21,7 +21,7 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/common/src/test/java/io/seata/common/util/BlobUtilsTest.java b/common/src/test/java/io/seata/common/util/BlobUtilsTest.java
index e65d917e7603051994af9638f5db7236dd342ab3..53a0a6217aeb29cc6e9bdc5713beb568817d6e04 100644
--- a/common/src/test/java/io/seata/common/util/BlobUtilsTest.java
+++ b/common/src/test/java/io/seata/common/util/BlobUtilsTest.java
@@ -21,8 +21,8 @@ import java.sql.SQLException;
 
 import javax.sql.rowset.serial.SerialBlob;
 
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -60,11 +60,11 @@ public class BlobUtilsTest {
      * Test input stream 2 string.
      */
     @Test
-    @Ignore
+    @Disabled
     public void testInputStream2String() {
         InputStream inputStream = BlobUtilsTest.class.getClassLoader().getResourceAsStream("test.txt");
         assertThat(BlobUtils.inputStream2String(inputStream)).isEqualTo("abc\n"
             + ":\"klsdf\n"
             + "2ks,x:\".,-3sd˚ø≤ø¬≥");
     }
-}
\ No newline at end of file
+}
diff --git a/common/src/test/java/io/seata/common/util/CollectionUtilsTest.java b/common/src/test/java/io/seata/common/util/CollectionUtilsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5eaa53ad751c3ebbf5d6f81bebd338b65578278b
--- /dev/null
+++ b/common/src/test/java/io/seata/common/util/CollectionUtilsTest.java
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.common.util;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Geng Zhang
+ */
+public class CollectionUtilsTest {
+
+    @Test
+    public void isSizeEquals() {
+        List<String> list0 = new ArrayList<>();
+        List<String> list1 = new ArrayList<>();
+        Assertions.assertTrue(CollectionUtils.isSizeEquals(null, null));
+        Assertions.assertFalse(CollectionUtils.isSizeEquals(null, list0));
+        Assertions.assertFalse(CollectionUtils.isSizeEquals(list1, null));
+        Assertions.assertTrue(CollectionUtils.isSizeEquals(list0, list1));
+
+        list0.add("111");
+        Assertions.assertFalse(CollectionUtils.isSizeEquals(list0, list1));
+        list1.add("111");
+        Assertions.assertTrue(CollectionUtils.isSizeEquals(list0, list1));
+    }
+}
\ No newline at end of file
diff --git a/common/src/test/java/io/seata/common/util/NetUtilTest.java b/common/src/test/java/io/seata/common/util/NetUtilTest.java
index 8ac10950cb91504059f39c4982db8f80175501ba..6e06ef690ed692c29a94eb698dc95c1b85c51a66 100644
--- a/common/src/test/java/io/seata/common/util/NetUtilTest.java
+++ b/common/src/test/java/io/seata/common/util/NetUtilTest.java
@@ -21,7 +21,7 @@ import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.net.UnknownHostException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -161,4 +161,4 @@ public class NetUtilTest {
         assertThat(NetUtil.getLocalAddress()).isNotNull();
     }
 
-}
\ No newline at end of file
+}
diff --git a/common/src/test/java/io/seata/common/util/StringUtilsTest.java b/common/src/test/java/io/seata/common/util/StringUtilsTest.java
index a6f2e04de15cc2fa7c7ed49247b440a82c7d53f8..1eae80462bf81c5027cf26d27b03472e1c1cb1d4 100644
--- a/common/src/test/java/io/seata/common/util/StringUtilsTest.java
+++ b/common/src/test/java/io/seata/common/util/StringUtilsTest.java
@@ -21,8 +21,9 @@ import java.sql.SQLException;
 
 import javax.sql.rowset.serial.SerialBlob;
 
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -30,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThat;
  * The type String utils test.
  *
  * @author Otis.z
+ * @author Geng Zhang
  * @date 2019 /2/20
  */
 public class StringUtilsTest {
@@ -78,10 +80,32 @@ public class StringUtilsTest {
      * Test input stream 2 string.
      */
     @Test
-    @Ignore
+    @Disabled
     public void testInputStream2String() throws IOException {
         InputStream inputStream = StringUtilsTest.class.getClassLoader().getResourceAsStream("test.txt");
         assertThat(StringUtils.inputStream2String(inputStream))
             .isEqualTo("abc\n" + ":\"klsdf\n" + "2ks,x:\".,-3sd˚ø≤ø¬≥");
     }
+
+    @Test
+    void testEquals() {
+        Assertions.assertTrue(StringUtils.equals("1", "1"));
+        Assertions.assertFalse(StringUtils.equals("1", "2"));
+        Assertions.assertFalse(StringUtils.equals(null, "1"));
+        Assertions.assertFalse(StringUtils.equals("1", null));
+        Assertions.assertFalse(StringUtils.equals("", null));
+        Assertions.assertFalse(StringUtils.equals(null, ""));
+    }
+
+    @Test
+    void testEqualsIgnoreCase() {
+        Assertions.assertTrue(StringUtils.equalsIgnoreCase("a", "a"));
+        Assertions.assertTrue(StringUtils.equalsIgnoreCase("a", "A"));
+        Assertions.assertTrue(StringUtils.equalsIgnoreCase("A", "a"));
+        Assertions.assertFalse(StringUtils.equalsIgnoreCase("1", "2"));
+        Assertions.assertFalse(StringUtils.equalsIgnoreCase(null, "1"));
+        Assertions.assertFalse(StringUtils.equalsIgnoreCase("1", null));
+        Assertions.assertFalse(StringUtils.equalsIgnoreCase("", null));
+        Assertions.assertFalse(StringUtils.equalsIgnoreCase(null, ""));
+    }
 }
diff --git a/common/src/test/resources/META-INF/seata/frenchhello/io.seata.common.loader.Hello b/common/src/test/resources/META-INF/seata/frenchhello/io.seata.common.loader.Hello
index 557a969ea42944901b706371e327fb2f3dafab3b..6b236a07b4806a5de5c064f10b1c96dbfe63d60a 100644
--- a/common/src/test/resources/META-INF/seata/frenchhello/io.seata.common.loader.Hello
+++ b/common/src/test/resources/META-INF/seata/frenchhello/io.seata.common.loader.Hello
@@ -1,5 +1,5 @@
 #
-#  Copyright 1999-2018 Alibaba Group Holding Ltd.
+#  Copyright 1999-2019 Seata.io Group.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
diff --git a/common/src/test/resources/META-INF/seata/io.seata.common.loader.Hello b/common/src/test/resources/META-INF/seata/io.seata.common.loader.Hello
index 1418d41f5a56de27d0ef4d89be3e1e979c6961c7..c3ebe7adaa3c826c4ee312ce2b5c8eb8d7b1f4dd 100644
--- a/common/src/test/resources/META-INF/seata/io.seata.common.loader.Hello
+++ b/common/src/test/resources/META-INF/seata/io.seata.common.loader.Hello
@@ -1,5 +1,5 @@
 #
-#  Copyright 1999-2018 Alibaba Group Holding Ltd.
+#  Copyright 1999-2019 Seata.io Group.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
diff --git a/common/src/test/resources/META-INF/services/io.seata.common.loader.Hello b/common/src/test/resources/META-INF/services/io.seata.common.loader.Hello
index 82fdd0efc41b2f122c34105f25ae422f4c2bd984..693b332b0035a187c4746f833676e25657043de7 100644
--- a/common/src/test/resources/META-INF/services/io.seata.common.loader.Hello
+++ b/common/src/test/resources/META-INF/services/io.seata.common.loader.Hello
@@ -1,6 +1,6 @@
 #
 #
-#  Copyright 1999-2018 Alibaba Group Holding Ltd.
+#  Copyright 1999-2019 Seata.io Group.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
diff --git a/common/src/test/resources/test.txt b/common/src/test/resources/test.txt
deleted file mode 100644
index 9df2d6bbba184eeb7f1591f9448e351b8385c3c7..0000000000000000000000000000000000000000
--- a/common/src/test/resources/test.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-abc
-:"klsdf
-2ks,x:".,-3sd˚ø≤ø¬≥
\ No newline at end of file
diff --git a/config/pom.xml b/config/pom.xml
index beccb795478ab9a79a967b0b5eb2eb426d4c971e..cfdf735708d9a990e40b3d4c67684db6b14e5584 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -32,18 +32,6 @@
         <module>seata-config-nacos</module>
         <module>seata-config-zk</module>
         <module>seata-config-all</module>
+        <module>seata-config-consul</module>
     </modules>
-
-    <dependencies>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
 </project>
diff --git a/config/seata-config-all/pom.xml b/config/seata-config-all/pom.xml
index 6e8a052bcae59cee851ac62dc335c0cf2127c816..3cf62928e1bac49a9d6203b4258a5078b54ddf48 100644
--- a/config/seata-config-all/pom.xml
+++ b/config/seata-config-all/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -29,14 +29,22 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-config-apollo</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-config-zk</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-config-nacos</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>seata-config-consul</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 
diff --git a/config/seata-config-apollo/pom.xml b/config/seata-config-apollo/pom.xml
index df01ab18dc1ccb757a6fb118dc1f0a73c7a88da2..20a4307a726c1b5a76f84a8e137d027dc652f590 100644
--- a/config/seata-config-apollo/pom.xml
+++ b/config/seata-config-apollo/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
         <dependency>
             <groupId>io.seata</groupId>
             <artifactId>seata-config-core</artifactId>
-            <version>${project.parent.version}</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>com.ctrip.framework.apollo</groupId>
diff --git a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java
index 561caef48429cf6f63c48ef9e7299f00c5c37d28..d1c1721a471a7158587de1220000b57a83352f83 100644
--- a/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java
+++ b/config/seata-config-apollo/src/main/java/io/seata/config/apollo/ApolloConfiguration.java
@@ -122,7 +122,7 @@ public class ApolloConfiguration extends AbstractConfiguration<ConfigChangeListe
 
     @Override
     public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) {
-        throw new NotSupportYetException("not support putConfigIfAbsent");
+        throw new NotSupportYetException("not support atomic operation putConfigIfAbsent");
     }
 
     @Override
diff --git a/config/seata-config-consul/pom.xml b/config/seata-config-consul/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c5c9de6d371e92e17b44d9429edd9023f2e33b0a
--- /dev/null
+++ b/config/seata-config-consul/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 1999-2019 Seata.io Group.
+  ~
+  ~  Licensed 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">
+    <parent>
+        <groupId>io.seata</groupId>
+        <artifactId>seata-config</artifactId>
+        <version>${revision}</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>seata-config-consul</artifactId>
+    <name>seata-config-consul ${project.version}</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.seata</groupId>
+            <artifactId>seata-config-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.ecwid.consul</groupId>
+            <artifactId>consul-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6c09c34af96aaaa7e52c52a0b06fe9c2ccc3d64
--- /dev/null
+++ b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfiguration.java
@@ -0,0 +1,276 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.config.consul;
+
+import com.ecwid.consul.v1.ConsulClient;
+import com.ecwid.consul.v1.QueryParams;
+import com.ecwid.consul.v1.Response;
+import com.ecwid.consul.v1.kv.model.GetValue;
+import com.ecwid.consul.v1.kv.model.PutParams;
+import io.seata.common.thread.NamedThreadFactory;
+import io.seata.config.AbstractConfiguration;
+import io.seata.config.ConfigChangeListener;
+import io.seata.config.ConfigFuture;
+import io.seata.config.Configuration;
+import io.seata.config.ConfigurationFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import static io.seata.config.ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR;
+import static io.seata.config.ConfigurationKeys.FILE_ROOT_CONFIG;
+
+/**
+ * @author xingfudeshi@gmail.com
+ * @date 2019/05/05
+ */
+public class ConsulConfiguration extends AbstractConfiguration<ConfigChangeListener> {
+    private volatile static ConsulConfiguration instance;
+    private volatile static ConsulClient client;
+
+    private static final Configuration FILE_CONFIG = ConfigurationFactory.FILE_INSTANCE;
+    private static final String SERVER_ADDR_KEY = "serverAddr";
+    private static final String CONFIG_TYPE = "consul";
+    private static final String FILE_CONFIG_KEY_PREFIX = FILE_ROOT_CONFIG + FILE_CONFIG_SPLIT_CHAR + CONFIG_TYPE + FILE_CONFIG_SPLIT_CHAR;
+    private static final int THREAD_POOL_NUM = 1;
+    private static final int MAP_INITIAL_CAPACITY = 8;
+    private static ExecutorService consulConfigExecutor = null;
+    private static ExecutorService consulNotifierExecutor = null;
+    private static ConcurrentMap<String, List<ConfigChangeListener>> configListenersMap = null;
+    private static ConcurrentMap<String, List<ConfigChangeNotifier>> configChangeNotifiersMap = null;
+
+    /**
+     * default watch timeout in second
+     */
+    private static final int DEFAULT_WATCH_TIMEOUT = 60;
+    private static final long CAS = 0L;
+
+
+    private ConsulConfiguration() {
+    }
+
+    /**
+     * get instance
+     *
+     * @return
+     */
+    public static ConsulConfiguration getInstance() {
+        if (null == instance) {
+            synchronized (ConsulConfiguration.class) {
+                if (null == instance) {
+                    consulConfigExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM,
+                        Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("consul-config-executor", THREAD_POOL_NUM));
+                    consulNotifierExecutor = new ThreadPoolExecutor(THREAD_POOL_NUM, THREAD_POOL_NUM,
+                        Integer.MAX_VALUE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory("consul-notifier-executor", THREAD_POOL_NUM));
+                    configListenersMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
+                    configChangeNotifiersMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
+                    instance = new ConsulConfiguration();
+                }
+            }
+
+        }
+        return instance;
+    }
+
+
+    @Override
+    public String getConfig(String dataId, String defaultValue, long timeoutMills) {
+        ConfigFuture configFuture = new ConfigFuture(dataId, defaultValue, ConfigFuture.ConfigOperation.GET, timeoutMills);
+        consulConfigExecutor.execute(() -> {
+            complete(getConsulClient().getKVValue(dataId), configFuture);
+        });
+        return (String) configFuture.get();
+    }
+
+    @Override
+    public boolean putConfig(String dataId, String content, long timeoutMills) {
+        ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigFuture.ConfigOperation.PUT, timeoutMills);
+        consulConfigExecutor.execute(() -> {
+            complete(getConsulClient().setKVValue(dataId, content), configFuture);
+        });
+        return (Boolean) configFuture.get();
+    }
+
+    @Override
+    public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) {
+        ConfigFuture configFuture = new ConfigFuture(dataId, content, ConfigFuture.ConfigOperation.PUTIFABSENT, timeoutMills);
+        consulConfigExecutor.execute(() -> {
+            PutParams putParams = new PutParams();
+            //Setting CAS to 0 means that this is an atomic operation, created when key does not exist.
+            putParams.setCas(CAS);
+            complete(getConsulClient().setKVValue(dataId, content, putParams), configFuture);
+        });
+        return (Boolean) configFuture.get();
+    }
+
+    @Override
+    public boolean removeConfig(String dataId, long timeoutMills) {
+        ConfigFuture configFuture = new ConfigFuture(dataId, null, ConfigFuture.ConfigOperation.REMOVE, timeoutMills);
+        consulConfigExecutor.execute(() -> {
+            complete(getConsulClient().deleteKVValue(dataId), configFuture);
+        });
+        return (Boolean) configFuture.get();
+    }
+
+    @Override
+    public void addConfigListener(String dataId, ConfigChangeListener listener) {
+        configListenersMap.putIfAbsent(dataId, new ArrayList<>());
+        configChangeNotifiersMap.putIfAbsent(dataId, new ArrayList<>());
+        ConfigChangeNotifier configChangeNotifier = new ConfigChangeNotifier(dataId, listener);
+        configChangeNotifiersMap.get(dataId).add(configChangeNotifier);
+        if (null != listener.getExecutor()) {
+            listener.getExecutor().submit(configChangeNotifier);
+        } else {
+            consulConfigExecutor.submit(configChangeNotifier);
+        }
+    }
+
+    @Override
+    public void removeConfigListener(String dataId, ConfigChangeListener listener) {
+        List<ConfigChangeListener> configChangeListeners = getConfigListeners(dataId);
+        if (configChangeListeners == null) {
+            return;
+        }
+        List<ConfigChangeListener> newChangeListenerList = new ArrayList<>();
+        for (ConfigChangeListener changeListener : configChangeListeners) {
+            if (!changeListener.equals(listener)) {
+                newChangeListenerList.add(changeListener);
+            }
+        }
+        configListenersMap.put(dataId, newChangeListenerList);
+        if (null != listener.getExecutor()) {
+            listener.getExecutor().shutdownNow();
+        }
+        //remove and stop the configChangeNotifier
+        List<ConfigChangeNotifier> configChangeNotifiers = configChangeNotifiersMap.get(dataId);
+        List<ConfigChangeNotifier> newConfigChangeNotifiers = new ArrayList<>();
+        for (ConfigChangeNotifier configChangeNotifier : configChangeNotifiers) {
+            if (!listener.equals(configChangeNotifier.getListener())) {
+                newConfigChangeNotifiers.add(configChangeNotifier);
+            } else {
+                configChangeNotifier.stop();
+            }
+        }
+        configChangeNotifiersMap.put(dataId, newConfigChangeNotifiers);
+    }
+
+    @Override
+    public List<ConfigChangeListener> getConfigListeners(String dataId) {
+        return configListenersMap.get(dataId);
+    }
+
+    @Override
+    public String getTypeName() {
+        return CONFIG_TYPE;
+    }
+
+
+    /**
+     * get consul client
+     *
+     * @return client
+     */
+    private static ConsulClient getConsulClient() {
+        if (null == client) {
+            synchronized (ConsulConfiguration.class) {
+                if (null == client) {
+                    client = new ConsulClient(FILE_CONFIG.getConfig(FILE_CONFIG_KEY_PREFIX + SERVER_ADDR_KEY));
+                }
+            }
+        }
+        return client;
+    }
+
+    /**
+     * complete the future
+     *
+     * @param response
+     * @param configFuture
+     */
+    private void complete(Response response, ConfigFuture configFuture) {
+        Object value = response.getValue();
+        if (null != response && null != value) {
+            if (value instanceof GetValue) {
+                configFuture.setResult(((GetValue) response.getValue()).getDecodedValue());
+            } else {
+                configFuture.setResult(response.getValue());
+            }
+        }
+    }
+
+    /**
+     * the type config change notifier
+     */
+    private static class ConfigChangeNotifier implements Runnable {
+        private final String dataId;
+        private final ConfigChangeListener listener;
+        private long consulIndex;
+        private boolean running;
+
+        public ConfigChangeNotifier(String dataId, ConfigChangeListener listener) {
+            this.dataId = dataId;
+            this.listener = listener;
+            this.consulIndex = getConsulClient().getKVValue(this.dataId).getConsulIndex();
+            this.running = true;
+        }
+
+        /**
+         * get the listener
+         *
+         * @return
+         */
+        public ConfigChangeListener getListener() {
+            return this.listener;
+        }
+
+        @Override
+        public void run() {
+            while (running) {
+                process();
+            }
+        }
+
+        /**
+         * process
+         */
+        private void process() {
+            QueryParams queryParams = new QueryParams(DEFAULT_WATCH_TIMEOUT, consulIndex);
+            Response<GetValue> response = getConsulClient().getKVValue(this.dataId, queryParams);
+            Long currentIndex = response.getConsulIndex();
+            if (currentIndex != null && currentIndex > consulIndex) {
+                GetValue getValue = response.getValue();
+                consulIndex = currentIndex;
+                for (ConfigChangeListener listener : configListenersMap.get(this.dataId)) {
+                    listener.receiveConfigInfo(getValue.getDecodedValue());
+                }
+            }
+
+        }
+
+        /**
+         * stop the notifier
+         */
+        public void stop() {
+            this.running = false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigurationProvider.java b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigurationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fb48f8f03836d44bd8078c92d0912f65f4b45f7
--- /dev/null
+++ b/config/seata-config-consul/src/main/java/io/seata/config/consul/ConsulConfigurationProvider.java
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.config.consul;
+
+import io.seata.common.loader.LoadLevel;
+import io.seata.config.Configuration;
+import io.seata.config.ConfigurationProvider;
+
+/**
+ * @author xingfudeshi@gmail.com
+ * @date 2019/05/05
+ */
+@LoadLevel(name = "Consul", order = 1)
+public class ConsulConfigurationProvider implements ConfigurationProvider {
+    @Override
+    public Configuration provide() {
+        return ConsulConfiguration.getInstance();
+    }
+}
\ No newline at end of file
diff --git a/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider b/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider
new file mode 100644
index 0000000000000000000000000000000000000000..d4de84820819bc367b8e490c8f76d16126afe554
--- /dev/null
+++ b/config/seata-config-consul/src/main/resources/META-INF/services/io.seata.config.ConfigurationProvider
@@ -0,0 +1 @@
+io.seata.config.consul.ConsulConfigurationProvider
\ No newline at end of file
diff --git a/config/seata-config-core/pom.xml b/config/seata-config-core/pom.xml
index da0224e8c3d208d5bfdd1e4b5aa0a952f3b072b1..1ebc1fbabeb776f48b8efe78138a47634fa4aa2d 100644
--- a/config/seata-config-core/pom.xml
+++ b/config/seata-config-core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-common</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>com.typesafe</groupId>
diff --git a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java
index 8f4ced0b101e09ca3cfbaabb4a6579a579a1eb81..866fddb8d67eec8836d9e0799ff7bcaf29b99755 100644
--- a/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java
+++ b/config/seata-config-core/src/main/java/io/seata/config/ConfigType.java
@@ -37,7 +37,11 @@ public enum ConfigType {
     /**
      * Apollo config type.
      */
-    Apollo;
+    Apollo,
+    /**
+     * Consul config type
+     */
+    Consul;
 
     /**
      * Gets type.
diff --git a/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java b/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java
index 1ef77b9d5a0a909788d5c11463da1db66aa564a8..7b5627d9000787bd632ad36090fdac489ef698b8 100644
--- a/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java
+++ b/config/seata-config-core/src/main/java/io/seata/config/FileConfiguration.java
@@ -25,11 +25,11 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
 import io.seata.common.thread.NamedThreadFactory;
 import io.seata.config.ConfigFuture.ConfigOperation;
 
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
 import org.apache.commons.lang.ObjectUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -185,18 +185,23 @@ public class FileConfiguration extends AbstractConfiguration<ConfigChangeListene
                     setFailResult(configFuture);
                     return;
                 }
-                if (configFuture.getOperation() == ConfigOperation.GET) {
-                    String result = CONFIG.getString(configFuture.getDataId());
-                    configFuture.setResult(result == null ? configFuture.getContent() : result);
-                } else if (configFuture.getOperation() == ConfigOperation.PUT) {
-                    //todo
-                    configFuture.setResult(Boolean.TRUE);
-                } else if (configFuture.getOperation() == ConfigOperation.PUTIFABSENT) {
-                    //todo
-                    configFuture.setResult(Boolean.TRUE);
-                } else if (configFuture.getOperation() == ConfigOperation.REMOVE) {
-                    //todo
-                    configFuture.setResult(Boolean.TRUE);
+                try {
+                    if (configFuture.getOperation() == ConfigOperation.GET) {
+                        String result = CONFIG.getString(configFuture.getDataId());
+                        configFuture.setResult(result);
+                    } else if (configFuture.getOperation() == ConfigOperation.PUT) {
+                        //todo
+                        configFuture.setResult(Boolean.TRUE);
+                    } else if (configFuture.getOperation() == ConfigOperation.PUTIFABSENT) {
+                        //todo
+                        configFuture.setResult(Boolean.TRUE);
+                    } else if (configFuture.getOperation() == ConfigOperation.REMOVE) {
+                        //todo
+                        configFuture.setResult(Boolean.TRUE);
+                    }
+                } catch (Exception e){
+                    setFailResult(configFuture);
+                    LOGGER.warn("Could not found property {}, try to use default value instead.", configFuture.getDataId());
                 }
             }
         }
diff --git a/config/seata-config-core/src/main/resources/file.conf b/config/seata-config-core/src/main/resources/file.conf
index 30801f29901834757ef6e68d5fbf6c4b1486a975..dc09514d367b205f6a0fdb8dfc45d462c7bddf20 100644
--- a/config/seata-config-core/src/main/resources/file.conf
+++ b/config/seata-config-core/src/main/resources/file.conf
@@ -69,4 +69,4 @@ client {
     retry.times = 30
   }
   report.retry.count = 5
-}
+}
\ No newline at end of file
diff --git a/config/seata-config-core/src/main/resources/registry.conf b/config/seata-config-core/src/main/resources/registry.conf
index 15677236a892397e6babed5c83f1263b842a56c2..1d6c35982564b2f8330a6a9bdb46f2aa12ae407c 100644
--- a/config/seata-config-core/src/main/resources/registry.conf
+++ b/config/seata-config-core/src/main/resources/registry.conf
@@ -45,7 +45,7 @@ registry {
 }
 
 config {
-  # file、nacos 、apollo、zk
+  # file、nacos 、apollo、zk、consul
   type = "file"
 
   nacos {
@@ -53,6 +53,9 @@ config {
     namespace = "public"
     cluster = "default"
   }
+  consul {
+    serverAddr = "127.0.0.1:8500"
+  }
   apollo {
     app.id = "seata-server"
     apollo.meta = "http://192.168.1.204:8801"
@@ -65,4 +68,4 @@ config {
   file {
     name = "file.conf"
   }
-}
+}
\ No newline at end of file
diff --git a/config/seata-config-nacos/pom.xml b/config/seata-config-nacos/pom.xml
index 6a8dc0814c9e222b1236c2a068fff6e15f4cf032..943bb525d16314decffee7bb54e5a42bac9ef83a 100644
--- a/config/seata-config-nacos/pom.xml
+++ b/config/seata-config-nacos/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java
index f38f0eedcadc487aafa7a921a4e2f0e64caaf2ea..5fe0a0175e5b5d8e3bb004ec70b8365e50fe555a 100644
--- a/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java
+++ b/config/seata-config-nacos/src/main/java/io/seata/config/nacos/NacosConfiguration.java
@@ -82,7 +82,7 @@ public class NacosConfiguration extends AbstractConfiguration<Listener> {
 
     @Override
     public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) {
-        throw new NotSupportYetException("not support putConfigIfAbsent");
+        throw new NotSupportYetException("not support atomic operation putConfigIfAbsent");
     }
 
     @Override
@@ -112,7 +112,7 @@ public class NacosConfiguration extends AbstractConfiguration<Listener> {
 
     @Override
     public List<Listener> getConfigListeners(String dataId) {
-        throw new NotSupportYetException("not support putConfigIfAbsent");
+        throw new NotSupportYetException("not support getConfigListeners");
     }
 
     private static Properties getConfigProperties() {
diff --git a/config/seata-config-zk/pom.xml b/config/seata-config-zk/pom.xml
index ab26a1185d1036a42f19fbc4c0d52bbbf6504aa2..d1694031a620e6626dfcc1df2a38f9783602d4be 100644
--- a/config/seata-config-zk/pom.xml
+++ b/config/seata-config-zk/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -34,12 +34,6 @@
         <dependency>
             <groupId>com.101tec</groupId>
             <artifactId>zkclient</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>slf4j-log4j12</artifactId>
-                    <groupId>org.slf4j</groupId>
-                </exclusion>
-            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java
index c5f4e332dd867bdf33e5b131a0c170a2242bee0b..f30e6fdac856724f6e9d253cac0e8f9d80801f41 100644
--- a/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java
+++ b/config/seata-config-zk/src/main/java/io/seata/config/zk/ZookeeperConfiguration.java
@@ -130,7 +130,7 @@ public class ZookeeperConfiguration extends AbstractConfiguration<IZkDataListene
 
     @Override
     public boolean putConfigIfAbsent(String dataId, String content, long timeoutMills) {
-        throw new NotSupportYetException("not support atom operation putConfigIfAbsent");
+        throw new NotSupportYetException("not support atomic operation putConfigIfAbsent");
     }
 
     @Override
diff --git a/core/pom.xml b/core/pom.xml
index 7e078dccfc7f4748a1969700e6be63da02f57e53..a6a71f8e60dd4515aefbe2b27e6ac8e3830ed300 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -29,21 +29,23 @@
     <name>seata-core ${project.version}</name>
 
     <dependencies>
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>fastjson</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-all</artifactId>
-        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-common</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -53,19 +55,6 @@
             <groupId>commons-pool</groupId>
             <artifactId>commons-pool</artifactId>
         </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
-    <build>
-        <extensions>
-            <extension>
-                <groupId>kr.motd.maven</groupId>
-                <artifactId>os-maven-plugin</artifactId>
-                <version>1.4.0.Final</version>
-            </extension>
-        </extensions>
-    </build>
+
 </project>
diff --git a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java
index abe610e43924192f34b6689ec77fb041775654fe..9aa741dd28dcaf3754de65586e880f74b25a8284 100644
--- a/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java
+++ b/core/src/main/java/io/seata/core/exception/AbstractExceptionHandler.java
@@ -41,6 +41,56 @@ public abstract class AbstractExceptionHandler {
          * @throws TransactionException the transaction exception
          */
         void execute(T request, S response) throws TransactionException;
+
+        /**
+         * on Success
+         *
+         * @param request
+         * @param response
+         */
+        void onSuccess(T request, S response);
+
+        /**
+         * onTransactionException
+         *
+         * @param request
+         * @param response
+         * @param exception
+         */
+        void onTransactionException(T request, S response, TransactionException exception);
+
+        /**
+         * on other exception
+         *
+         * @param request
+         * @param response
+         * @param exception
+         */
+        void onException(T request, S response, Exception exception);
+
+    }
+
+    public abstract class AbstractCallback<T extends AbstractTransactionRequest, S extends AbstractTransactionResponse>
+        implements Callback<T, S> {
+
+        @Override
+        public void onSuccess(T request, S response) {
+            response.setResultCode(ResultCode.Success);
+        }
+
+        @Override
+        public void onTransactionException(T request, S response,
+            TransactionException tex) {
+            response.setTransactionExceptionCode(tex.getCode());
+            response.setResultCode(ResultCode.Failed);
+            response.setMsg("TransactionException[" + tex.getMessage() + "]");
+        }
+
+        @Override
+        public void onException(T request, S response, Exception rex) {
+            response.setResultCode(ResultCode.Failed);
+            response.setMsg("RuntimeException[" + rex.getMessage() + "]");
+        }
     }
 
     /**
@@ -51,19 +101,14 @@ public abstract class AbstractExceptionHandler {
      * @param response the response
      */
     public void exceptionHandleTemplate(Callback callback, AbstractTransactionRequest request,
-                                        AbstractTransactionResponse response) {
+        AbstractTransactionResponse response) {
         try {
             callback.execute(request, response);
-            response.setResultCode(ResultCode.Success);
-
+            callback.onSuccess(request, response);
         } catch (TransactionException tex) {
-            response.setTransactionExceptionCode(tex.getCode());
-            response.setResultCode(ResultCode.Failed);
-            response.setMsg("TransactionException[" + tex.getMessage() + "]");
-
+            callback.onTransactionException(request, response, tex);
         } catch (RuntimeException rex) {
-            response.setResultCode(ResultCode.Failed);
-            response.setMsg("RuntimeException[" + rex.getMessage() + "]");
+            callback.onException(request, response, rex);
         }
     }
 
diff --git a/core/src/main/java/io/seata/core/model/GlobalStatus.java b/core/src/main/java/io/seata/core/model/GlobalStatus.java
index d8e813d17b57eab6d2501908799efa5534850fc6..037d1a64c8c478a3400d0ab4e559682a3d8fd394 100644
--- a/core/src/main/java/io/seata/core/model/GlobalStatus.java
+++ b/core/src/main/java/io/seata/core/model/GlobalStatus.java
@@ -16,9 +16,7 @@
 package io.seata.core.model;
 
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * Status of global transaction.
diff --git a/core/src/main/java/io/seata/core/model/ResourceManager.java b/core/src/main/java/io/seata/core/model/ResourceManager.java
index 21fd5ea2710c836b0827f759ae0ba195057426ab..9d6214f339d8bddac13a11fd87383221855bcad4 100644
--- a/core/src/main/java/io/seata/core/model/ResourceManager.java
+++ b/core/src/main/java/io/seata/core/model/ResourceManager.java
@@ -46,8 +46,9 @@ public interface ResourceManager extends ResourceManagerInbound, ResourceManager
     Map<String, Resource> getManagedResources();
 
     /**
-     * get the BranchType
-     * @return
+     * Get the BranchType.
+     *
+     * @return The BranchType of ResourceManager.
      */
     BranchType getBranchType();
 }
diff --git a/core/src/main/java/io/seata/core/model/ResourceManagerInbound.java b/core/src/main/java/io/seata/core/model/ResourceManagerInbound.java
index e841b39f0c40082c9007e94d545a0738c10e60ba..2162bf4aa2021f5189ec5d848eff39cb36f7a022 100644
--- a/core/src/main/java/io/seata/core/model/ResourceManagerInbound.java
+++ b/core/src/main/java/io/seata/core/model/ResourceManagerInbound.java
@@ -15,11 +15,12 @@
  */
 package io.seata.core.model;
 
-import io.seata.core.exception.TransactionException;
 import io.seata.core.exception.TransactionException;
 
 /**
+ * Resource Manager.
  *
+ * Control a branch transaction commit or rollback.
  *
  * @author sharajava
  */
@@ -28,28 +29,28 @@ public interface ResourceManagerInbound {
     /**
      * Commit a branch transaction.
      *
-     * s@param branchType the branch type
+     * @param branchType      the branch type
      * @param xid             Transaction id.
      * @param branchId        Branch id.
      * @param resourceId      Resource id.
      * @param applicationData Application data bind with this branch.
      * @return Status of the branch after committing.
      * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
-     * out.
+     *                              out.
      */
     BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException;
 
     /**
      * Rollback a branch transaction.
      *
-     * @param branchType the branch type
+     * @param branchType      the branch type
      * @param xid             Transaction id.
      * @param branchId        Branch id.
      * @param resourceId      Resource id.
      * @param applicationData Application data bind with this branch.
      * @return Status of the branch after rollbacking.
      * @throws TransactionException Any exception that fails this will be wrapped with TransactionException and thrown
-     * out.
+     *                              out.
      */
     BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException;
 }
diff --git a/core/src/main/java/io/seata/core/model/ResourceManagerOutbound.java b/core/src/main/java/io/seata/core/model/ResourceManagerOutbound.java
index 5e25206b85e067e15d93ee3d9dc5735fdd260e71..a8330032469fbacfbe927121cc85b1849135a353 100644
--- a/core/src/main/java/io/seata/core/model/ResourceManagerOutbound.java
+++ b/core/src/main/java/io/seata/core/model/ResourceManagerOutbound.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.model;
 
-import io.seata.core.exception.TransactionException;
 import io.seata.core.exception.TransactionException;
 
 /**
diff --git a/core/src/main/java/io/seata/core/model/TransactionManager.java b/core/src/main/java/io/seata/core/model/TransactionManager.java
index 0770d6bba3245e5625ac1fac8a37f76a71b85131..78779f269b665b6a1c0225203bf8caed855bd6a3 100644
--- a/core/src/main/java/io/seata/core/model/TransactionManager.java
+++ b/core/src/main/java/io/seata/core/model/TransactionManager.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.model;
 
-import io.seata.core.exception.TransactionException;
 import io.seata.core.exception.TransactionException;
 
 /**
diff --git a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java
index 688cada84e229b8674092b103e7d101055ef0b2f..f7b0d197239cc59cbd08bb8843457d2aa1ebbda0 100644
--- a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyRequest.java
@@ -214,37 +214,55 @@ public abstract class AbstractIdentifyRequest extends AbstractMessage {
 
     @Override
     public boolean decode(ByteBuf in) {
-        try {
-            short len = in.readShort();
-            if (len > 0) {
-                byte[] bs = new byte[len];
-                in.readBytes(bs);
-                this.setVersion(new String(bs, UTF8));
-            }
-            len = in.readShort();
-            if (len > 0) {
-                byte[] bs = new byte[len];
-                in.readBytes(bs);
-                this.setApplicationId(new String(bs, UTF8));
-            }
-            len = in.readShort();
-            if (len > 0) {
-                byte[] bs = new byte[len];
-                in.readBytes(bs);
-                this.setTransactionServiceGroup(new String(bs, UTF8));
-            }
-            len = in.readShort();
-            if (len > 0) {
-                byte[] bs = new byte[len];
-                in.readBytes(bs);
-                this.setExtraData(new String(bs, UTF8));
-            }
-        } catch (Exception exx) {
-            LOGGER.error(exx.getMessage() + this);
+
+        short len;
+        if (in.readableBytes() < 2) {
             return false;
         }
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug(in.writerIndex() == in.readerIndex() ? "true" : "false" + this);
+        len = in.readShort();
+
+        if (in.readableBytes() < len) {
+            return false;
+        }
+        byte[] bs = new byte[len];
+        in.readBytes(bs);
+        this.setVersion(new String(bs, UTF8));
+
+        if (in.readableBytes() < 2) {
+            return false;
+        }
+        len = in.readShort();
+
+        if (in.readableBytes() < len) {
+            return false;
+        }
+        bs = new byte[len];
+        in.readBytes(bs);
+        this.setApplicationId(new String(bs, UTF8));
+
+        if (in.readableBytes() < 2) {
+            return false;
+        }
+        len = in.readShort();
+
+        if (in.readableBytes() < len) {
+            return false;
+        }
+        bs = new byte[len];
+        in.readBytes(bs);
+        this.setTransactionServiceGroup(new String(bs, UTF8));
+
+        if (in.readableBytes() < 2) {
+            return false;
+        }
+        len = in.readShort();
+
+        if (in.readableBytes() >= len) {
+            bs = new byte[len];
+            in.readBytes(bs);
+            this.setExtraData(new String(bs, UTF8));
+        } else {
+            //maybe null
         }
 
         return true;
diff --git a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java
index 75ec8ac00efe7c3b5ca79227d99fd0aee6520152..e6c0fd8e7fafa8dfccbad8a47cf494167a27d837 100644
--- a/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java
+++ b/core/src/main/java/io/seata/core/protocol/AbstractIdentifyResponse.java
@@ -102,25 +102,22 @@ public abstract class AbstractIdentifyResponse extends AbstractResultMessage {
 
     @Override
     public boolean decode(ByteBuf in) {
-        int i = in.readableBytes();
-        if (i < 3) {
+        if (in.readableBytes() < 3) {
             return false;
         }
-        i -= 3;
         this.identified = (in.readByte() == 1);
-
         short len = in.readShort();
-        if (len > 0) {
-            if (i < len) {
-                return false;
-            }
-
-            byte[] bs = new byte[len];
-            in.readBytes(bs);
-            this.setVersion(new String(bs, UTF8));
+        if (len <= 0) {
+            return false;
         }
-
+        if (in.readableBytes() < len) {
+            return false;
+        }
+        byte[] bs = new byte[len];
+        in.readBytes(bs);
+        this.setVersion(new String(bs, UTF8));
         return true;
+
     }
 
     @Override
diff --git a/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java b/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java
index df1e2bb1e630586a2b12f524b1c328c6c70cb7c9..187eb10dc29295b7cc2ae01bc1632560881940e6 100644
--- a/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java
+++ b/core/src/main/java/io/seata/core/protocol/AbstractResultMessage.java
@@ -130,22 +130,18 @@ public abstract class AbstractResultMessage extends AbstractMessage implements M
 
     @Override
     public boolean decode(ByteBuf in) {
-        int i = in.readableBytes();
-        if (i < 1) {
+        if (in.readableBytes() < 1) {
             return false;
         }
         setResultCode(ResultCode.get(in.readByte()));
-        i--;
         if (resultCode == ResultCode.Failed) {
-            if (i < 2) {
+            if (in.readableBytes() < 2) {
                 return false;
             }
             short len = in.readShort();
-            i -= 2;
-            if (i < len) {
+            if (in.readableBytes() < len) {
                 return false;
             }
-
             if (len > 0) {
                 byte[] msg = new byte[len];
                 in.readBytes(msg);
diff --git a/core/src/main/java/io/seata/core/protocol/MergeResultMessage.java b/core/src/main/java/io/seata/core/protocol/MergeResultMessage.java
index 6f8a72327075e7b70ffbcf3d1dcc3c2a481bab76..79bc2678cc01101ac18bd47aeee73876078e7618 100644
--- a/core/src/main/java/io/seata/core/protocol/MergeResultMessage.java
+++ b/core/src/main/java/io/seata/core/protocol/MergeResultMessage.java
@@ -84,12 +84,10 @@ public class MergeResultMessage extends AbstractMessage implements MergeMessage
 
     @Override
     public boolean decode(ByteBuf in) {
-        int i = in.readableBytes();
-        if (i < 4) { return false; }
+        if (in.readableBytes() < 4) { return false; }
 
-        i -= 4;
         int length = in.readInt();
-        if (i < length) { return false; }
+        if (in.readableBytes() < length) { return false; }
         byte[] buffer = new byte[length];
         in.readBytes(buffer);
         ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
diff --git a/core/src/main/java/io/seata/core/protocol/MergedWarpMessage.java b/core/src/main/java/io/seata/core/protocol/MergedWarpMessage.java
index 27e946b35ad31e574c1294ccf08c9d65d600b196..6b4c3f847e2d882d41f58c3757a11b7721da85a5 100644
--- a/core/src/main/java/io/seata/core/protocol/MergedWarpMessage.java
+++ b/core/src/main/java/io/seata/core/protocol/MergedWarpMessage.java
@@ -74,14 +74,12 @@ public class MergedWarpMessage extends AbstractMessage implements Serializable,
 
     @Override
     public boolean decode(ByteBuf in) {
-        int i = in.readableBytes();
-        if (i < 4) {
+        if (in.readableBytes() < 4) {
             return false;
         }
 
-        i -= 4;
         int length = in.readInt();
-        if (i < length) {
+        if (in.readableBytes() < length) {
             return false;
         }
 
diff --git a/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java b/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java
index f1914bd8a171993abd67e1fc5059b69f23c795e4..b2ffda034d46b301103b3bf3ea867129604d24be 100644
--- a/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/RegisterRMRequest.java
@@ -86,75 +86,78 @@ public class RegisterRMRequest extends AbstractIdentifyRequest implements Serial
 
     @Override
     public boolean decode(ByteBuf in) {
-        int i = in.readableBytes();
-        if (i < 1) {
+
+        if (in.readableBytes() < 2) {
             return false;
         }
-
         short len = in.readShort();
-        i -= 2;
         if (len > 0) {
-            if (i < len) {
+            if (in.readableBytes() < len) {
                 return false;
-            } else {
-                i -= len;
             }
             byte[] bs = new byte[len];
             in.readBytes(bs);
             this.setVersion(new String(bs, UTF8));
+        } else {
+            return false;
+        }
+        if (in.readableBytes() < 2) {
+            return false;
         }
-
         len = in.readShort();
-        i -= 2;
+
         if (len > 0) {
-            if (i < len) {
+            if (in.readableBytes() < len) {
                 return false;
-            } else {
-                i -= len;
             }
             byte[] bs = new byte[len];
             in.readBytes(bs);
             this.setApplicationId(new String(bs, UTF8));
         }
 
+        if (in.readableBytes() < 2) {
+            return false;
+        }
         len = in.readShort();
-        i -= 2;
-        if (len > 0) {
-            if (i < len) {
-                return false;
-            } else {
-                i -= len;
-            }
-            byte[] bs = new byte[len];
-            in.readBytes(bs);
-            this.setTransactionServiceGroup(new String(bs, UTF8));
+
+        if (in.readableBytes() < len) {
+            return false;
         }
+        byte[] bs = new byte[len];
+        in.readBytes(bs);
+        this.setTransactionServiceGroup(new String(bs, UTF8));
 
+        if (in.readableBytes() < 2) {
+            return false;
+        }
         len = in.readShort();
-        i -= 2;
+
         if (len > 0) {
-            if (i < len) {
+            if (in.readableBytes() < len) {
                 return false;
-            } else {
-                i -= len;
             }
-            byte[] bs = new byte[len];
+            bs = new byte[len];
             in.readBytes(bs);
             this.setExtraData(new String(bs, UTF8));
         }
 
-        int iLen = in.readInt();
-        i -= 4;
+        int iLen;
+        if (in.readableBytes() < 4) {
+            return false;
+        }
+        iLen = in.readInt();
+
         if (iLen > 0) {
-            if (i < iLen) {
+            if (in.readableBytes() < iLen) {
                 return false;
-            } else {
-                i -= iLen;
             }
-            byte[] bs = new byte[iLen];
+            bs = new byte[iLen];
             in.readBytes(bs);
             this.setResourceIds(new String(bs, UTF8));
+            return true;
         }
+        //maybe null
+
         return true;
     }
 
diff --git a/core/src/main/java/io/seata/core/protocol/Version.java b/core/src/main/java/io/seata/core/protocol/Version.java
index b6239d739c74feb8894f56874ca718d9d0ecb524..3f5a40470e71efcebe125749b3f86fcb6a191363 100644
--- a/core/src/main/java/io/seata/core/protocol/Version.java
+++ b/core/src/main/java/io/seata/core/protocol/Version.java
@@ -31,7 +31,7 @@ public class Version {
     /**
      * The constant CURRENT.
      */
-    public static final String CURRENT = "0.5.1";
+    public static final String CURRENT = "0.5.2";
 
     /**
      * The constant VERSION_MAP.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java
index 4bd5963acdf6cfec199bba5b9f0342cf838f1a82..d8dd64d86aa0f46cddf369f201f3cd1956ac0ef0 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndRequest.java
@@ -197,48 +197,62 @@ public abstract class AbstractBranchEndRequest extends AbstractTransactionReques
 
     @Override
     public boolean decode(ByteBuf in) {
-        int leftLen = in.readableBytes();
-        int read = 0;
-        int xidLen = in.readShort();
-        leftLen -= 2;
-        if (xidLen > 0) {
-            if (leftLen < xidLen) {
-                return false;
-            }
-            byte[] bs = new byte[xidLen];
-            in.readBytes(bs);
-            setXid(new String(bs, UTF8));
-            leftLen -= xidLen;
+        int xidLen = 0;
+        if (in.readableBytes() >= 2) {
+            xidLen = in.readShort();
+        }
+        if (xidLen <= 0) {
+            return false;
+        }
+        if (in.readableBytes() < xidLen) {
+            return false;
+        }
+        byte[] bs = new byte[xidLen];
+        in.readBytes(bs);
+        setXid(new String(bs, UTF8));
+
+        if (in.readableBytes() < 8) {
+            return false;
         }
         this.branchId = in.readLong();
-        leftLen -= 8;
+
+        if (in.readableBytes() < 1) {
+            return false;
+        }
         this.branchType = BranchType.get(in.readByte());
-        leftLen--;
 
-        int resourceIdLen = in.readShort();
-        leftLen -= 2;
-        if (resourceIdLen > 0) {
-            if (leftLen < resourceIdLen) {
-                return false;
-            }
-            byte[] bs = new byte[resourceIdLen];
-            in.readBytes(bs);
-            setResourceId(new String(bs, UTF8));
-            leftLen -= resourceIdLen;
+        int resourceIdLen = 0;
+        if (in.readableBytes() < 2) {
+            return false;
         }
+        resourceIdLen = in.readShort();
+
+        if (resourceIdLen <= 0) {
+            return false;
+        }
+        if (in.readableBytes() < resourceIdLen) {
+            return false;
+        }
+        bs = new byte[resourceIdLen];
+        in.readBytes(bs);
+        setResourceId(new String(bs, UTF8));
+
+        int applicationDataLen = 0;
+        if (in.readableBytes() < 4) {
+            return false;
+        }
+        applicationDataLen = in.readInt();
 
-        int applicationDataLen = in.readInt();
-        leftLen -= 4;
         if (applicationDataLen > 0) {
-            if (leftLen < applicationDataLen) {
+            if (in.readableBytes() < applicationDataLen) {
                 return false;
             }
-            byte[] bs = new byte[applicationDataLen];
+           bs = new byte[applicationDataLen];
             in.readBytes(bs);
             setApplicationData(new String(bs, UTF8));
-            leftLen -= applicationDataLen;
+        }else{
+            //application data may be null
         }
-
         return true;
     }
 
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java
index 7452404148649d11a4296da0c297121a442051fc..6aafd9e54a00bd1b91e6f08f0c152d3c63b21ae2 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractBranchEndResponse.java
@@ -17,9 +17,8 @@ package io.seata.core.protocol.transaction;
 
 import java.nio.ByteBuffer;
 
-import io.seata.core.model.BranchStatus;
-
 import io.netty.buffer.ByteBuf;
+import io.seata.core.model.BranchStatus;
 
 /**
  * The type Abstract branch end response.
@@ -131,13 +130,24 @@ public abstract class AbstractBranchEndResponse extends AbstractTransactionRespo
         if (!s) {
             return s;
         }
-        short xidLen = in.readShort();
-        if (xidLen > 0) {
-            byte[] bs = new byte[xidLen];
-            in.readBytes(bs);
-            this.setXid(new String(bs, UTF8));
+        short xidLen;
+        if (in.readableBytes() < 2) {
+            return false;
+        }
+        xidLen = in.readShort();
+        if (in.readableBytes() < xidLen) {
+            return false;
+        }
+        byte[] bs = new byte[xidLen];
+        in.readBytes(bs);
+        this.setXid(new String(bs, UTF8));
+        if (in.readableBytes() < 8) {
+            return false;
         }
         branchId = in.readLong();
+        if (in.readableBytes() < 1) {
+            return false;
+        }
         branchStatus = BranchStatus.get(in.readByte());
         return true;
     }
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionRequest.java
index 3452467bfa0ef96d6a8eb60c24f7674f9a85c10c..399b7492c7b448d4a48bdc4bc357823265204d4f 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionRequest.java
@@ -19,7 +19,6 @@ import java.nio.ByteBuffer;
 
 import io.seata.core.protocol.AbstractMessage;
 import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.RpcContext;
 
 /**
  * The type Abstract transaction request.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionResponse.java b/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionResponse.java
index 46aa783a202f94b33f0d72f8cb57ad2ee81ac3b9..8bfe35257194742372b67d5f9ac9282a4dc0f52a 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionResponse.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/AbstractTransactionResponse.java
@@ -17,11 +17,9 @@ package io.seata.core.protocol.transaction;
 
 import java.nio.ByteBuffer;
 
-import io.seata.core.exception.TransactionExceptionCode;
-import io.seata.core.protocol.AbstractResultMessage;
-
 import io.netty.buffer.ByteBuf;
 import io.seata.core.exception.TransactionExceptionCode;
+import io.seata.core.protocol.AbstractResultMessage;
 
 /**
  * The type Abstract transaction response.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchCommitRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchCommitRequest.java
index dae191733da071a9780e3cf97888d705a428454f..29368392b6fe0d9e88ec19ee4bdb7da0e27405c0 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/BranchCommitRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchCommitRequest.java
@@ -17,7 +17,6 @@ package io.seata.core.protocol.transaction;
 
 import io.seata.core.protocol.AbstractMessage;
 import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.RpcContext;
 
 /**
  * The type Branch commit request.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java
index 5be09408dfc566d69b7c3aee2e178693f4a8630b..e58c20ba6a2cbc9519e439204534b28d426b68e5 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchRegisterRequest.java
@@ -20,7 +20,6 @@ import java.nio.ByteBuffer;
 import io.seata.core.model.BranchType;
 import io.seata.core.protocol.MergedMessage;
 import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.RpcContext;
 
 /**
  * The type Branch register request.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java
index b21f6350b0594e9ee63450d2d9e974600e15103e..8bc0a02dc6fdc48e2fa8df7f9d5cb8a6e88d3394 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchReportRequest.java
@@ -21,7 +21,6 @@ import io.seata.core.model.BranchStatus;
 import io.seata.core.model.BranchType;
 import io.seata.core.protocol.MergedMessage;
 import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.RpcContext;
 
 /**
  * The type Branch report request.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/BranchRollbackRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/BranchRollbackRequest.java
index c18722b274526e130f84a7f3b44d29bdac44ff53..e8a95cfb4dfa91e63fdfea6f14b372c0b7f1e81f 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/BranchRollbackRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/BranchRollbackRequest.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.protocol.transaction;
 
-import io.seata.core.rpc.RpcContext;
 import io.seata.core.rpc.RpcContext;
 
 /**
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java
index ca8a4eb879d00716e7773ca496715f29e027725c..2fef4d5218d0029c355f1c2b8d07b868e30aea03 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalBeginRequest.java
@@ -19,7 +19,6 @@ import java.nio.ByteBuffer;
 
 import io.seata.core.protocol.MergedMessage;
 import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.RpcContext;
 
 /**
  * The type Global begin request.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalCommitRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalCommitRequest.java
index aacca8ef16387daf46c9669fce00369d76232454..bcf76379e06e01a3dc986904b9f6987226040ccd 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalCommitRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalCommitRequest.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.protocol.transaction;
 
-import io.seata.core.rpc.RpcContext;
 import io.seata.core.rpc.RpcContext;
 
 /**
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryRequest.java
index 42fc69bc42b1e4831987c3adc34f889bdd2776bb..048778f2dc5f1f37b326493d8cde0116db103de1 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalLockQueryRequest.java
@@ -17,7 +17,6 @@ package io.seata.core.protocol.transaction;
 
 import io.seata.core.protocol.MergedMessage;
 import io.seata.core.rpc.RpcContext;
-import io.seata.core.rpc.RpcContext;
 
 /**
  * The type Global lock query request.
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalRollbackRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalRollbackRequest.java
index 757a615c080301c9b350966ddf515bf205828b40..50bb00a5b0277dc40dccb79b3fdb6f534562347c 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalRollbackRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalRollbackRequest.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.protocol.transaction;
 
-import io.seata.core.rpc.RpcContext;
 import io.seata.core.rpc.RpcContext;
 
 /**
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/GlobalStatusRequest.java b/core/src/main/java/io/seata/core/protocol/transaction/GlobalStatusRequest.java
index 4b67fd8b9366cefe6048455ed9e4c80e98bb0ab7..ec1aff8ab75cc879af24ff9ca61da05768630f79 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/GlobalStatusRequest.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/GlobalStatusRequest.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.protocol.transaction;
 
-import io.seata.core.rpc.RpcContext;
 import io.seata.core.rpc.RpcContext;
 
 /**
diff --git a/core/src/main/java/io/seata/core/protocol/transaction/TCInboundHandler.java b/core/src/main/java/io/seata/core/protocol/transaction/TCInboundHandler.java
index 5b1b2ecfe0929982d60fd7334db4a05c4e7c5716..2b92b2ae72107b0ed2d2808194a3ebf954e62e6b 100644
--- a/core/src/main/java/io/seata/core/protocol/transaction/TCInboundHandler.java
+++ b/core/src/main/java/io/seata/core/protocol/transaction/TCInboundHandler.java
@@ -15,7 +15,6 @@
  */
 package io.seata.core.protocol.transaction;
 
-import io.seata.core.rpc.RpcContext;
 import io.seata.core.rpc.RpcContext;
 
 /**
diff --git a/core/src/main/java/io/seata/core/rpc/netty/MessageCodecHandler.java b/core/src/main/java/io/seata/core/rpc/netty/MessageCodecHandler.java
index 32a56449e0e45c457d50ffc54c96197ea80cef0f..5235541202075183bba4b0bf07b285896ae01da6 100644
--- a/core/src/main/java/io/seata/core/rpc/netty/MessageCodecHandler.java
+++ b/core/src/main/java/io/seata/core/rpc/netty/MessageCodecHandler.java
@@ -18,14 +18,13 @@ package io.seata.core.rpc.netty;
 import java.nio.ByteBuffer;
 import java.util.List;
 
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageCodec;
 import io.seata.core.protocol.AbstractMessage;
 import io.seata.core.protocol.HeartbeatMessage;
 import io.seata.core.protocol.MessageCodec;
 import io.seata.core.protocol.RpcMessage;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -119,60 +118,46 @@ public class MessageCodecHandler extends ByteToMessageCodec<RpcMessage> {
 
     @Override
     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        int begin = in.readerIndex();
-        int magicIndex = getMagicIndex(in);
-        if (magicIndex == NOT_FOUND_INDEX) {
-            LOGGER.error("codec decode not found magic offset");
-            in.skipBytes(in.readableBytes());
-            return;
-        }
-        if (magicIndex != 0 && LOGGER.isInfoEnabled()) {
-            LOGGER.info("please notice magicIndex is not zero offset!!!");
-        }
-        in.skipBytes(magicIndex - in.readerIndex());
+
         if (in.readableBytes() < HEAD_LENGTH) {
-            LOGGER.error("decode less than header length");
             return;
         }
-        byte[] buffer = new byte[HEAD_LENGTH];
-        in.readBytes(buffer);
-        ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
-        short magic = byteBuffer.getShort();
-        if (magic != MAGIC) {
-            LOGGER.error("decode error,will close channel:" + ctx.channel());
+        in.markReaderIndex();
+        short protocol = in.readShort();
+        if (protocol != MAGIC) {
+            String emsg = "decode error,Unknown protocol: " + protocol + ",will close channel:" + ctx.channel();
+            LOGGER.error(emsg);
             ctx.channel().close();
             return;
         }
 
-        int flag = byteBuffer.getShort();
+        int flag = (int)in.readShort();
+
         boolean isHeartbeat = (FLAG_HEARTBEAT & flag) > 0;
         boolean isRequest = (FLAG_REQUEST & flag) > 0;
         boolean isSeataCodec = (FLAG_SEATA_CODEC & flag) > 0;
 
         short bodyLength = 0;
         short typeCode = 0;
-        if (!isSeataCodec) { bodyLength = byteBuffer.getShort(); } else { typeCode = byteBuffer.getShort(); }
-        long msgId = byteBuffer.getLong();
-
+        if (!isSeataCodec) { bodyLength = in.readShort(); } else { typeCode = in.readShort(); }
+        long msgId = in.readLong();
         if (isHeartbeat) {
             RpcMessage rpcMessage = new RpcMessage();
             rpcMessage.setId(msgId);
             rpcMessage.setAsync(true);
             rpcMessage.setHeartbeat(isHeartbeat);
             rpcMessage.setRequest(isRequest);
-
             if (isRequest) {
                 rpcMessage.setBody(HeartbeatMessage.PING);
             } else {
                 rpcMessage.setBody(HeartbeatMessage.PONG);
             }
-
             out.add(rpcMessage);
             return;
         }
 
         if (bodyLength > 0 && in.readableBytes() < bodyLength) {
-            in.readerIndex(begin);
+            in.resetReaderIndex();
             return;
         }
 
@@ -186,8 +171,7 @@ public class MessageCodecHandler extends ByteToMessageCodec<RpcMessage> {
             if (isSeataCodec) {
                 MessageCodec msgCodec = AbstractMessage.getMsgInstanceByCode(typeCode);
                 if (!msgCodec.decode(in)) {
-                    LOGGER.error(msgCodec + " decode error.");
-                    in.readerIndex(begin);
+                    in.resetReaderIndex();
                     return;
                 }
                 rpcMessage.setBody(msgCodec);
@@ -240,19 +224,4 @@ public class MessageCodecHandler extends ByteToMessageCodec<RpcMessage> {
         throw new RuntimeException("hessianDeserialize not support");
 
     }
-
-    private static int getMagicIndex(ByteBuf in) {
-        boolean found = false;
-        int readIndex = in.readerIndex();
-        int begin = 0;
-        while (readIndex < in.writerIndex()) {
-            if (in.getByte(readIndex) == MAGIC_HALF && in.getByte(readIndex + 1) == MAGIC_HALF) {
-                begin = readIndex;
-                found = true;
-                break;
-            }
-            ++readIndex;
-        }
-        return found ? begin : NOT_FOUND_INDEX;
-    }
 }
diff --git a/core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java b/core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java
index c2e4928a2efa50fd044547b58158c8b0ee909255..3f68380574dfb16cfb8dc7d0cbdecbdd888a1438 100644
--- a/core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java
+++ b/core/src/main/java/io/seata/core/rpc/netty/RmRpcClient.java
@@ -26,6 +26,11 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.util.concurrent.EventExecutorGroup;
 import io.seata.common.exception.FrameworkErrorCode;
 import io.seata.common.exception.FrameworkException;
 import io.seata.common.thread.NamedThreadFactory;
@@ -37,16 +42,6 @@ import io.seata.core.protocol.HeartbeatMessage;
 import io.seata.core.protocol.RegisterRMRequest;
 import io.seata.core.protocol.RegisterRMResponse;
 import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole;
-
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandler.Sharable;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.timeout.IdleStateEvent;
-import io.netty.util.concurrent.EventExecutorGroup;
-import io.seata.core.protocol.AbstractMessage;
-import io.seata.core.protocol.HeartbeatMessage;
-import io.seata.core.protocol.RegisterRMRequest;
-import io.seata.core.protocol.RegisterRMResponse;
 import org.apache.commons.pool.impl.GenericKeyedObjectPool.Config;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -192,7 +187,7 @@ public final class RmRpcClient extends AbstractRpcRemotingClient {
 
     @Override
     protected NettyPoolKey.TransactionRole getTransactionRole() {
-        return NettyPoolKey.TransactionRole.RMROLE;
+        return TransactionRole.RMROLE;
     }
 
     @Override
@@ -313,7 +308,7 @@ public final class RmRpcClient extends AbstractRpcRemotingClient {
             }
             channelFromPool = nettyClientKeyPool.borrowObject(poolKeyMap.get(serverAddress));
         } catch (Exception exx) {
-            LOGGER.error(FrameworkErrorCode.RegistRM.getErrCode(), "register RM failed.", exx);
+            LOGGER.error(FrameworkErrorCode.RegisterRM.getErrCode(), "register RM failed.", exx);
             throw new FrameworkException("can not register RM,err:" + exx.getMessage());
         }
         return channelFromPool;
@@ -387,6 +382,10 @@ public final class RmRpcClient extends AbstractRpcRemotingClient {
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info("register to RM resourceId:" + resourceId);
         }
+        if (channels.isEmpty()) {
+            reconnect(transactionServiceGroup);
+            return;
+        }
         synchronized (channels) {
             for (Map.Entry<String, Channel> entry : channels.entrySet()) {
                 String serverAddress = entry.getKey();
diff --git a/core/src/main/java/io/seata/core/rpc/netty/RpcServerHandler.java b/core/src/main/java/io/seata/core/rpc/netty/RpcServerHandler.java
deleted file mode 100644
index 2070285297b0190ffa17cb57a2bc5875d1384a97..0000000000000000000000000000000000000000
--- a/core/src/main/java/io/seata/core/rpc/netty/RpcServerHandler.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *  Copyright 1999-2019 Seata.io Group.
- *
- *  Licensed 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 io.seata.core.rpc.netty;
-
-import io.netty.channel.ChannelHandler.Sharable;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.handler.timeout.IdleState;
-import io.netty.handler.timeout.IdleStateEvent;
-import io.netty.util.collection.LongObjectHashMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The type Rpc server handler.
- *
- * @author jimin.jm @alibaba-inc.com
- * @date 2018 /9/12
- */
-@Sharable
-public class RpcServerHandler extends ChannelInboundHandlerAdapter {
-    private static final Logger LOGGER = LoggerFactory.getLogger(RpcServerHandler.class);
-
-    private final LongObjectHashMap compressTable = new LongObjectHashMap(16, 0.5f);
-
-    /**
-     * Instantiates a new Rpc server handler.
-     */
-    public RpcServerHandler() {
-        LOGGER.info("init server handler");
-
-    }
-
-    /*
-    @Override
-    @SuppressWarnings("unchecked")
-    public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
-        LOGGER.info("server:" + msg.toString());
-        final Channel channel = ctx.channel();
-        final String request = (String)msg;
-        try {
-            ctx.writeAndFlush(request, ctx.voidPromise());
-            super.channelRead(ctx, msg);
-            LOGGER.info("server:" + msg);
-
-        } catch (Exception e) {
-            LOGGER.error("when try flush error", e);
-        }
-    }
-    */
-
-    @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-        LOGGER.info("Server channel read:");
-    }
-
-    @Override
-    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
-        ctx.fireUserEventTriggered(evt);
-        if (evt instanceof IdleStateEvent) {
-
-            IdleStateEvent event = (IdleStateEvent)evt;
-
-            if (event.state().equals(IdleState.READER_IDLE)) {
-
-                LOGGER.error("READER_IDLE");
-                ctx.close();
-
-            } else if (event.state().equals(IdleState.WRITER_IDLE)) {
-
-            } else if (event.state().equals(IdleState.ALL_IDLE)) {
-
-                LOGGER.error("ALL_IDLE");
-
-            }
-
-        }
-    }
-
-    //@Override
-    //protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
-    //    LOGGER.info("server channel read0:" + msg.toString());
-    //    final Channel channel = ctx.channel();
-    //    try {
-    //        ctx.writeAndFlush(msg, ctx.voidPromise());
-    //        super.channelRead(ctx, msg);
-    //        LOGGER.info("server:" + msg);
-    //
-    //    } catch (Exception e) {
-    //        LOGGER.error("when try flush error", e);
-    //    }
-    //}
-
-    @Override
-    public void channelActive(ChannelHandlerContext ctx) throws Exception {
-        super.channelActive(ctx);
-        LOGGER.info("channel active for ServerProxyHandler at :[{}]", ctx.channel());
-    }
-
-    @Override
-    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-        super.channelInactive(ctx);
-        LOGGER.info("channel inactive for ServerProxyHandler at :[{}],[{}]", ctx.channel(),
-            ctx.channel().remoteAddress());
-    }
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        ctx.close();
-        LOGGER.info("channel error:" + cause.getMessage());
-    }
-}
diff --git a/core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java b/core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java
index 662e71787000ab7e988fa817a9d635ef7d6d057b..cf146db41574d2376608d97d5328c0214dfb22dc 100644
--- a/core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java
+++ b/core/src/main/java/io/seata/core/rpc/netty/TmRpcClient.java
@@ -15,15 +15,12 @@
  */
 package io.seata.core.rpc.netty;
 
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.util.concurrent.EventExecutorGroup;
 import io.seata.common.exception.FrameworkErrorCode;
 import io.seata.common.exception.FrameworkException;
 import io.seata.common.thread.NamedThreadFactory;
@@ -38,18 +35,19 @@ import io.seata.core.protocol.RegisterTMRequest;
 import io.seata.core.protocol.RegisterTMResponse;
 import io.seata.core.protocol.ResultCode;
 import io.seata.core.protocol.transaction.GlobalBeginResponse;
-import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole;
-
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandler.Sharable;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.timeout.IdleState;
-import io.netty.handler.timeout.IdleStateEvent;
-import io.netty.util.concurrent.EventExecutorGroup;
 import org.apache.commons.pool.impl.GenericKeyedObjectPool.Config;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * The type Rpc client.
  *
diff --git a/core/src/main/logback.xml b/core/src/main/logback.xml
index 91e1a440a4be4fad25e75c187a327ebb3aa3a0eb..409c0d43ce87b271716f7085898813e2f12e8384 100644
--- a/core/src/main/logback.xml
+++ b/core/src/main/logback.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
   -->
 <configuration debug="false">
 
-    <!-- 日志输出级别 -->
+    <!-- log output level -->
     <root level="INFO">
         <appender-ref ref="STDOUT" />
     </root>
diff --git a/core/src/test/java/io/seata/core/context/ContextCoreTest.java b/core/src/test/java/io/seata/core/context/ContextCoreTest.java
index 724d02dd2e98917a7ecf7ecb508b20c3b01f86ca..6fc75d5000cff4dc97d23045dee8548c284f32c0 100644
--- a/core/src/test/java/io/seata/core/context/ContextCoreTest.java
+++ b/core/src/test/java/io/seata/core/context/ContextCoreTest.java
@@ -15,7 +15,7 @@
  */
 package io.seata.core.context;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/core/src/test/java/io/seata/core/context/RootContextTest.java b/core/src/test/java/io/seata/core/context/RootContextTest.java
index aebe5eb96cf5b16b47be26c87aaf5c734c3c09ad..6909b5e108e3963a328dfbebf18ca88e8ee7d629 100644
--- a/core/src/test/java/io/seata/core/context/RootContextTest.java
+++ b/core/src/test/java/io/seata/core/context/RootContextTest.java
@@ -17,7 +17,8 @@ package io.seata.core.context;
 
 import io.seata.common.exception.ShouldNeverHappenException;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -70,17 +71,19 @@ public class RootContextTest {
     /**
      * Test assert not in global transaction with exception.
      */
-    @Test(expected = ShouldNeverHappenException.class)
+    @Test
     public void testAssertNotInGlobalTransactionWithException() {
-        try {
-            RootContext.assertNotInGlobalTransaction();
-            RootContext.bind(DEFAULT_XID);
-            RootContext.assertNotInGlobalTransaction();
-        } finally {
-            //clear
-            RootContext.unbind();
-            assertThat(RootContext.getXID()).isNull();
-        }
+        Assertions.assertThrows(ShouldNeverHappenException.class, () -> {
+            try {
+                RootContext.assertNotInGlobalTransaction();
+                RootContext.bind(DEFAULT_XID);
+                RootContext.assertNotInGlobalTransaction();
+            } finally {
+                //clear
+                RootContext.unbind();
+                assertThat(RootContext.getXID()).isNull();
+            }
+        });
     }
 
     /**
diff --git a/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java b/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java
index 6c8e48c66274c4f2d0478a2f0d0d0c6cd9f850ce..4431e78c8bb4d696fc3b5ee66021254819f0271a 100644
--- a/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java
+++ b/core/src/test/java/io/seata/core/message/BranchCommitRequestTest.java
@@ -20,8 +20,8 @@ import io.seata.core.protocol.transaction.BranchCommitRequest;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.UnpooledByteBufAllocator;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Branch commit request test.
@@ -46,7 +46,7 @@ public class BranchCommitRequestTest {
         branchCommitRequest.setResourceId("resource1");
         branchCommitRequest.setApplicationData("app1");
 
-        Assert.assertEquals("xid=127.0.0.1:9999:39875642,branchId=1,branchType=AT,"
+        Assertions.assertEquals("xid=127.0.0.1:9999:39875642,branchId=1,branchType=AT,"
             + "resourceId=resource1,applicationData=app1", branchCommitRequest.toString());
 
     }
@@ -68,10 +68,10 @@ public class BranchCommitRequestTest {
 
         BranchCommitRequest decodeBranchCommitRequest = new BranchCommitRequest();
         decodeBranchCommitRequest.decode(byteBuffer);
-        Assert.assertEquals(decodeBranchCommitRequest.getXid(), branchCommitRequest.getXid());
-        Assert.assertEquals(decodeBranchCommitRequest.getBranchId(), branchCommitRequest.getBranchId());
-        Assert.assertEquals(decodeBranchCommitRequest.getResourceId(), branchCommitRequest.getResourceId());
-        Assert.assertEquals(decodeBranchCommitRequest.getApplicationData(), branchCommitRequest.getApplicationData());
-        Assert.assertEquals(decodeBranchCommitRequest.getBranchType(), branchCommitRequest.getBranchType());
+        Assertions.assertEquals(decodeBranchCommitRequest.getXid(), branchCommitRequest.getXid());
+        Assertions.assertEquals(decodeBranchCommitRequest.getBranchId(), branchCommitRequest.getBranchId());
+        Assertions.assertEquals(decodeBranchCommitRequest.getResourceId(), branchCommitRequest.getResourceId());
+        Assertions.assertEquals(decodeBranchCommitRequest.getApplicationData(), branchCommitRequest.getApplicationData());
+        Assertions.assertEquals(decodeBranchCommitRequest.getBranchType(), branchCommitRequest.getBranchType());
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java b/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java
index 2fb414ad85dcb51725ffce0442792997b447fcdf..03ad73179936ef3006c123da4ddf95f417081c41 100644
--- a/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java
+++ b/core/src/test/java/io/seata/core/message/BranchCommitResponseTest.java
@@ -21,8 +21,8 @@ import io.seata.core.protocol.transaction.BranchCommitResponse;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.UnpooledByteBufAllocator;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Branch commit response test.
@@ -42,7 +42,7 @@ public class BranchCommitResponseTest {
         branchCommitResponse.setBranchStatus(BranchStatus.PhaseOne_Done);
         branchCommitResponse.setResultCode(ResultCode.Success);
         branchCommitResponse.setMsg("");
-        Assert.assertEquals(
+        Assertions.assertEquals(
             "xid=127.0.0.1:8091:123456,branchId=2345678,branchStatus=PhaseOne_Done,result code =Success,getMsg =",
             branchCommitResponse.toString());
 
@@ -64,12 +64,12 @@ public class BranchCommitResponseTest {
 
         BranchCommitResponse decodeBranchCommitResponse = new BranchCommitResponse();
         decodeBranchCommitResponse.decode(byteBuffer);
-        Assert.assertEquals(decodeBranchCommitResponse.getXid(), branchCommitResponse.getXid());
-        Assert.assertEquals(decodeBranchCommitResponse.getBranchId(), branchCommitResponse.getBranchId());
-        Assert.assertEquals(decodeBranchCommitResponse.getResultCode(), branchCommitResponse.getResultCode());
-        Assert.assertEquals(decodeBranchCommitResponse.getBranchStatus(), branchCommitResponse.getBranchStatus());
-        Assert.assertEquals(decodeBranchCommitResponse.getTransactionExceptionCode(),
+        Assertions.assertEquals(decodeBranchCommitResponse.getXid(), branchCommitResponse.getXid());
+        Assertions.assertEquals(decodeBranchCommitResponse.getBranchId(), branchCommitResponse.getBranchId());
+        Assertions.assertEquals(decodeBranchCommitResponse.getResultCode(), branchCommitResponse.getResultCode());
+        Assertions.assertEquals(decodeBranchCommitResponse.getBranchStatus(), branchCommitResponse.getBranchStatus());
+        Assertions.assertEquals(decodeBranchCommitResponse.getTransactionExceptionCode(),
             branchCommitResponse.getTransactionExceptionCode());
-        Assert.assertEquals(decodeBranchCommitResponse.getMsg(), branchCommitResponse.getMsg());
+        Assertions.assertEquals(decodeBranchCommitResponse.getMsg(), branchCommitResponse.getMsg());
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java b/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java
index 0b06c0be6d5723ea85d969614eb8b9ca11b45928..c26a97401afd4d554c077355722a17d37bcbdc24 100644
--- a/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java
+++ b/core/src/test/java/io/seata/core/message/BranchRegisterRequestTest.java
@@ -20,8 +20,8 @@ import java.nio.ByteBuffer;
 import io.seata.core.model.BranchType;
 import io.seata.core.protocol.transaction.BranchRegisterRequest;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Branch register request test.
@@ -37,7 +37,7 @@ public class BranchRegisterRequestTest {
         branchRegisterRequest.setBranchType(BranchType.AT);
         branchRegisterRequest.setResourceId("resource1");
         branchRegisterRequest.setLockKey("lock_key_1");
-        Assert.assertEquals("xid=127.0.0.1:8091:1249853,branchType=AT,resourceId=resource1,lockKey=lock_key_1",
+        Assertions.assertEquals("xid=127.0.0.1:8091:1249853,branchType=AT,resourceId=resource1,lockKey=lock_key_1",
             branchRegisterRequest.toString());
 
     }
@@ -59,10 +59,10 @@ public class BranchRegisterRequestTest {
         byteBuffer.flip();
         BranchRegisterRequest decodeBranchRegisterRequest = new BranchRegisterRequest();
         decodeBranchRegisterRequest.decode(byteBuffer);
-        Assert.assertEquals(branchRegisterRequest.getXid(), decodeBranchRegisterRequest.getXid());
-        Assert.assertEquals(branchRegisterRequest.getLockKey(), decodeBranchRegisterRequest.getLockKey());
-        Assert.assertEquals(branchRegisterRequest.getResourceId(), decodeBranchRegisterRequest.getResourceId());
-        Assert.assertEquals(branchRegisterRequest.getApplicationData(),
+        Assertions.assertEquals(branchRegisterRequest.getXid(), decodeBranchRegisterRequest.getXid());
+        Assertions.assertEquals(branchRegisterRequest.getLockKey(), decodeBranchRegisterRequest.getLockKey());
+        Assertions.assertEquals(branchRegisterRequest.getResourceId(), decodeBranchRegisterRequest.getResourceId());
+        Assertions.assertEquals(branchRegisterRequest.getApplicationData(),
             decodeBranchRegisterRequest.getApplicationData());
     }
 }
diff --git a/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java b/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java
index ee9a80835945bb146113ca99c8a813fbf7efb377..ef431c229ef921f4f9d64cceb86198316a897b46 100644
--- a/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java
+++ b/core/src/test/java/io/seata/core/message/BranchRegisterResponseTest.java
@@ -18,8 +18,8 @@ package io.seata.core.message;
 import io.seata.core.protocol.ResultCode;
 import io.seata.core.protocol.transaction.BranchRegisterResponse;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Branch register response test.
@@ -37,7 +37,7 @@ public class BranchRegisterResponseTest {
         branchRegisterResponse.setBranchId(123457L);
         branchRegisterResponse.setResultCode(ResultCode.Success);
         branchRegisterResponse.setMsg("");
-        Assert.assertEquals(
+        Assertions.assertEquals(
             "BranchRegisterResponse: branchId=123457,result code =Success,getMsg =",
             branchRegisterResponse.toString());
 
diff --git a/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java b/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java
index 6061b55a98913b19e4cf4dc7d8dba150fe3dadb5..4a9d177836ddf10ba841314f41c2869bd7e8672d 100644
--- a/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java
+++ b/core/src/test/java/io/seata/core/message/BranchReportRequestTest.java
@@ -21,8 +21,8 @@ import io.seata.core.model.BranchStatus;
 import io.seata.core.model.BranchType;
 import io.seata.core.protocol.transaction.BranchReportRequest;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Branch report request test.
@@ -40,7 +40,7 @@ public class BranchReportRequestTest {
         branchReportRequest.setResourceId("resource003");
         branchReportRequest.setStatus(BranchStatus.PhaseOne_Timeout);
         branchReportRequest.setApplicationData("test app data");
-        Assert.assertEquals(
+        Assertions.assertEquals(
             "xid=127.0.0.1:8091:1249853,branchId=3,resourceId=resource003,status=PhaseOne_Timeout,"
                 + "applicationData=test app"
                 + " data",
@@ -69,11 +69,11 @@ public class BranchReportRequestTest {
 
         BranchReportRequest decodeBranchReportRequest = new BranchReportRequest();
         decodeBranchReportRequest.decode(byteBuffer);
-        Assert.assertEquals(branchReportRequest.getXid(), decodeBranchReportRequest.getXid());
-        Assert.assertEquals(branchReportRequest.getBranchId(), decodeBranchReportRequest.getBranchId());
-        Assert.assertEquals(branchReportRequest.getResourceId(), decodeBranchReportRequest.getResourceId());
-        Assert.assertEquals(branchReportRequest.getStatus(), decodeBranchReportRequest.getStatus());
-        Assert.assertEquals(branchReportRequest.getApplicationData(), decodeBranchReportRequest.getApplicationData());
-        Assert.assertEquals(branchReportRequest.getBranchType(), decodeBranchReportRequest.getBranchType());
+        Assertions.assertEquals(branchReportRequest.getXid(), decodeBranchReportRequest.getXid());
+        Assertions.assertEquals(branchReportRequest.getBranchId(), decodeBranchReportRequest.getBranchId());
+        Assertions.assertEquals(branchReportRequest.getResourceId(), decodeBranchReportRequest.getResourceId());
+        Assertions.assertEquals(branchReportRequest.getStatus(), decodeBranchReportRequest.getStatus());
+        Assertions.assertEquals(branchReportRequest.getApplicationData(), decodeBranchReportRequest.getApplicationData());
+        Assertions.assertEquals(branchReportRequest.getBranchType(), decodeBranchReportRequest.getBranchType());
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/message/CodecTest.java b/core/src/test/java/io/seata/core/message/CodecTest.java
index 929d2601a285a88e452904d8175d6b976d5fb819..d963a78b45b1c214532fea2adfd87bad7e2a444b 100644
--- a/core/src/test/java/io/seata/core/message/CodecTest.java
+++ b/core/src/test/java/io/seata/core/message/CodecTest.java
@@ -20,8 +20,8 @@ import java.nio.ByteBuffer;
 import io.seata.core.protocol.ResultCode;
 import io.seata.core.protocol.transaction.BranchRegisterResponse;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Codec test.
@@ -47,7 +47,7 @@ public class CodecTest {
         BranchRegisterResponse rs = new BranchRegisterResponse();
         rs.decode(byteBuffer);
 
-        Assert.assertEquals(response.getBranchId(), rs.getBranchId());
-        Assert.assertEquals(response.getResultCode(), rs.getResultCode());
+        Assertions.assertEquals(response.getBranchId(), rs.getBranchId());
+        Assertions.assertEquals(response.getResultCode(), rs.getResultCode());
     }
 }
diff --git a/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java b/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java
index 3d879a7f4c110be0b2db1ca1feb11154025cba59..bcfc6fdd0fa6d2251f49f2271d1f07f1e1369ba5 100644
--- a/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java
+++ b/core/src/test/java/io/seata/core/message/GlobalBeginRequestTest.java
@@ -20,8 +20,8 @@ import java.util.Arrays;
 
 import io.seata.core.protocol.transaction.GlobalBeginRequest;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Global begin request test.
@@ -42,7 +42,7 @@ public class GlobalBeginRequestTest {
         globalBeginRequest.setTransactionName("tran 1");
         System.out.println(globalBeginRequest.toString());
 
-        Assert.assertEquals("timeout=60000,transactionName=tran 1", globalBeginRequest.toString());
+        Assertions.assertEquals("timeout=60000,transactionName=tran 1", globalBeginRequest.toString());
     }
 
     /**
@@ -58,7 +58,7 @@ public class GlobalBeginRequestTest {
         byte[] encodeResult = globalBeginRequest.encode();
         String encodeResultStr = Arrays.toString(encodeResult);
 
-        Assert.assertEquals("[0, 0, -22, 96, 0, 6, 116, 114, 97, 110, 32, 49]", encodeResultStr);
+        Assertions.assertEquals("[0, 0, -22, 96, 0, 6, 116, 114, 97, 110, 32, 49]", encodeResultStr);
     }
 
     /**
@@ -80,7 +80,7 @@ public class GlobalBeginRequestTest {
         GlobalBeginRequest decodeGlobalBeginRequest = new GlobalBeginRequest();
         decodeGlobalBeginRequest.decode(byteBuffer);
         System.out.println(decodeGlobalBeginRequest);
-        Assert.assertEquals(globalBeginRequest.getTimeout(), decodeGlobalBeginRequest.getTimeout());
-        Assert.assertEquals(globalBeginRequest.getTransactionName(), decodeGlobalBeginRequest.getTransactionName());
+        Assertions.assertEquals(globalBeginRequest.getTimeout(), decodeGlobalBeginRequest.getTimeout());
+        Assertions.assertEquals(globalBeginRequest.getTransactionName(), decodeGlobalBeginRequest.getTransactionName());
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java b/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java
index fa81c21756b0d66b65d5b9196092e1f9822868fd..6ce6a651df8990a261f230ae8f05aae01dbe69d7 100644
--- a/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java
+++ b/core/src/test/java/io/seata/core/message/GlobalCommitResponseTest.java
@@ -23,8 +23,8 @@ import io.seata.core.protocol.ResultCode;
 import io.seata.core.protocol.transaction.GlobalCommitResponse;
 
 import org.apache.commons.lang.StringUtils;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Global commit response test.
@@ -49,7 +49,7 @@ public class GlobalCommitResponseTest {
 
         System.out.println(globalCommitResponse.toString());
 
-        Assert.assertEquals("globalStatus=Committed,ResultCode=Success,Msg=OK", globalCommitResponse.toString());
+        Assertions.assertEquals("globalStatus=Committed,ResultCode=Success,Msg=OK", globalCommitResponse.toString());
     }
 
     /**
@@ -72,7 +72,7 @@ public class GlobalCommitResponseTest {
         String encodeResultStr = Arrays.toString(encodeResult);
         System.out.println(encodeResultStr);
 
-        Assert.assertEquals("[1, 0, 9]", encodeResultStr);
+        Assertions.assertEquals("[1, 0, 9]", encodeResultStr);
     }
 
     /**
@@ -100,10 +100,10 @@ public class GlobalCommitResponseTest {
 
         System.out.println(decodeGlobalCommitResponse.toString());
 
-        Assert.assertEquals(globalCommitResponse.getGlobalStatus(), decodeGlobalCommitResponse.getGlobalStatus());
-        Assert.assertEquals(globalCommitResponse.getResultCode(), decodeGlobalCommitResponse.getResultCode());
+        Assertions.assertEquals(globalCommitResponse.getGlobalStatus(), decodeGlobalCommitResponse.getGlobalStatus());
+        Assertions.assertEquals(globalCommitResponse.getResultCode(), decodeGlobalCommitResponse.getResultCode());
         //success response do not have msg
-        Assert.assertTrue(StringUtils.isBlank(decodeGlobalCommitResponse.getMsg()));
+        Assertions.assertTrue(StringUtils.isBlank(decodeGlobalCommitResponse.getMsg()));
     }
 
     /**
@@ -131,8 +131,8 @@ public class GlobalCommitResponseTest {
 
         System.out.println(decodeGlobalCommitResponse.toString());
 
-        Assert.assertEquals(globalCommitResponse.getGlobalStatus(), decodeGlobalCommitResponse.getGlobalStatus());
-        Assert.assertEquals(globalCommitResponse.getResultCode(), decodeGlobalCommitResponse.getResultCode());
-        Assert.assertEquals(globalCommitResponse.getMsg(), decodeGlobalCommitResponse.getMsg());
+        Assertions.assertEquals(globalCommitResponse.getGlobalStatus(), decodeGlobalCommitResponse.getGlobalStatus());
+        Assertions.assertEquals(globalCommitResponse.getResultCode(), decodeGlobalCommitResponse.getResultCode());
+        Assertions.assertEquals(globalCommitResponse.getMsg(), decodeGlobalCommitResponse.getMsg());
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java b/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java
index c2e6da1bab55715ebbc70e5c752091cd03c991d6..0723153c77837489a69cea5ff3048b5339377f46 100644
--- a/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java
+++ b/core/src/test/java/io/seata/core/message/GlobalRollbackRequestTest.java
@@ -19,8 +19,8 @@ import java.nio.ByteBuffer;
 
 import io.seata.core.protocol.transaction.GlobalRollbackRequest;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Global rollback request test.
@@ -35,7 +35,7 @@ public class GlobalRollbackRequestTest {
         GlobalRollbackRequest globalRollbackRequest = new GlobalRollbackRequest();
         globalRollbackRequest.setXid("127.0.0.1:8091:1249853");
         globalRollbackRequest.setExtraData("test_extra_data");
-        Assert.assertEquals("xid=127.0.0.1:8091:1249853,extraData=test_extra_data", globalRollbackRequest.toString());
+        Assertions.assertEquals("xid=127.0.0.1:8091:1249853,extraData=test_extra_data", globalRollbackRequest.toString());
     }
 
     /**
@@ -52,7 +52,7 @@ public class GlobalRollbackRequestTest {
         byteBuffer.flip();
         GlobalRollbackRequest decodeGlobalRollbackRequest = new GlobalRollbackRequest();
         decodeGlobalRollbackRequest.decode(byteBuffer);
-        Assert.assertEquals(globalRollbackRequest.getXid(), decodeGlobalRollbackRequest.getXid());
-        Assert.assertEquals(globalRollbackRequest.getExtraData(), decodeGlobalRollbackRequest.getExtraData());
+        Assertions.assertEquals(globalRollbackRequest.getXid(), decodeGlobalRollbackRequest.getXid());
+        Assertions.assertEquals(globalRollbackRequest.getExtraData(), decodeGlobalRollbackRequest.getExtraData());
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java b/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java
index 39c6c50fd34ca2233f6f456a7baefff5520721a6..854275290cb1f6443e79f6bad178c834207968cf 100644
--- a/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java
+++ b/core/src/test/java/io/seata/core/message/RegisterTMResponseTest.java
@@ -18,8 +18,8 @@ package io.seata.core.message;
 import io.seata.core.protocol.RegisterTMResponse;
 import io.seata.core.protocol.ResultCode;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Register tm response test.
@@ -39,7 +39,7 @@ public class RegisterTMResponseTest {
         registerTMResponse.setIdentified(true);
         registerTMResponse.setResultCode(ResultCode.Success);
 
-        Assert.assertEquals("version=1,extraData=null,identified=true,resultCode=Success,msg=null",
+        Assertions.assertEquals("version=1,extraData=null,identified=true,resultCode=Success,msg=null",
             registerTMResponse.toString());
 
     }
diff --git a/core/src/test/java/io/seata/core/model/BranchStatusTest.java b/core/src/test/java/io/seata/core/model/BranchStatusTest.java
index 9840d94f3206867a9543f9d211548fe262250b7f..105ce064cfb525f81c7b9fd8d3d1ebad37be978b 100644
--- a/core/src/test/java/io/seata/core/model/BranchStatusTest.java
+++ b/core/src/test/java/io/seata/core/model/BranchStatusTest.java
@@ -16,11 +16,12 @@
 package io.seata.core.model;
 
 import io.seata.common.exception.ShouldNeverHappenException;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * A unit test for {@link BranchStatus}
+ *
  * @author Lay
  * @date 2019/3/6
  */
@@ -32,23 +33,23 @@ public class BranchStatusTest {
     @Test
     public void testGetCode() {
         int code = BranchStatus.Registered.getCode();
-        Assert.assertEquals(code, REGISTERED_CODE);
+        Assertions.assertEquals(code, REGISTERED_CODE);
     }
 
     @Test
     public void testGetWithByte() {
-        BranchStatus branchStatus = BranchStatus.get((byte)REGISTERED_CODE);
-        Assert.assertEquals(branchStatus, BranchStatus.Registered);
+        BranchStatus branchStatus = BranchStatus.get((byte) REGISTERED_CODE);
+        Assertions.assertEquals(branchStatus, BranchStatus.Registered);
     }
 
     @Test
     public void testGetWithInt() {
         BranchStatus branchStatus = BranchStatus.get(REGISTERED_CODE);
-        Assert.assertEquals(branchStatus, BranchStatus.Registered);
+        Assertions.assertEquals(branchStatus, BranchStatus.Registered);
     }
 
-    @Test(expected = ShouldNeverHappenException.class)
+    @Test
     public void testGetException() {
-        BranchStatus.get(NONE);
+        Assertions.assertThrows(ShouldNeverHappenException.class, () -> BranchStatus.get(NONE));
     }
 }
diff --git a/core/src/test/java/io/seata/core/model/BranchTypeTest.java b/core/src/test/java/io/seata/core/model/BranchTypeTest.java
index f2dfa744d05f33a51434a6b337b89e8824fbe9f7..78c6f80781558930c6c4e6a54bb4898b13be1f65 100644
--- a/core/src/test/java/io/seata/core/model/BranchTypeTest.java
+++ b/core/src/test/java/io/seata/core/model/BranchTypeTest.java
@@ -15,11 +15,12 @@
  */
 package io.seata.core.model;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * A unit test for {@link BranchType}
+ *
  * @author Lay
  * @date 2019/3/6
  */
@@ -31,30 +32,30 @@ public class BranchTypeTest {
     @Test
     public void testOrdinal() {
         int ordinal = BranchType.AT.ordinal();
-        Assert.assertEquals(AT_ORDINAL, ordinal);
+        Assertions.assertEquals(AT_ORDINAL, ordinal);
     }
 
     @Test
     public void testGetWithOrdinal() {
-        BranchType type  = BranchType.get(BranchType.AT.ordinal());
-        Assert.assertEquals(type, BranchType.AT);
+        BranchType type = BranchType.get(BranchType.AT.ordinal());
+        Assertions.assertEquals(type, BranchType.AT);
     }
 
     @Test
     public void testGetWithByte() {
-        BranchType branchStatus = BranchType.get((byte)AT_ORDINAL);
-        Assert.assertEquals(branchStatus, BranchType.AT);
+        BranchType branchStatus = BranchType.get((byte) AT_ORDINAL);
+        Assertions.assertEquals(branchStatus, BranchType.AT);
     }
 
     @Test
     public void testGetWithInt() {
         BranchType branchStatus = BranchType.get(AT_ORDINAL);
-        Assert.assertEquals(branchStatus, BranchType.AT);
+        Assertions.assertEquals(branchStatus, BranchType.AT);
     }
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test
     public void testGetException() {
-        BranchType.get(NONE);
+        Assertions.assertThrows(IllegalArgumentException.class, () -> BranchType.get(NONE));
     }
 
 
diff --git a/core/src/test/java/io/seata/core/model/GlobalStatusTest.java b/core/src/test/java/io/seata/core/model/GlobalStatusTest.java
index ec8e103b87faa9375300a5eb5e7ffc1e292cb986..8f2e026baf8b084a2374ca21e7e22d55f9cc6a9d 100644
--- a/core/src/test/java/io/seata/core/model/GlobalStatusTest.java
+++ b/core/src/test/java/io/seata/core/model/GlobalStatusTest.java
@@ -15,11 +15,12 @@
  */
 package io.seata.core.model;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * A unit test for {@link GlobalStatus}
+ *
  * @author Lay
  * @date 2019/3/6
  */
@@ -30,24 +31,24 @@ public class GlobalStatusTest {
     @Test
     public void testGetCode() {
         int code = GlobalStatus.Begin.getCode();
-        Assert.assertEquals(code, BEGIN_CODE);
+        Assertions.assertEquals(code, BEGIN_CODE);
     }
 
     @Test
     public void testGetWithByte() {
-        GlobalStatus branchStatus = GlobalStatus.get((byte)BEGIN_CODE);
-        Assert.assertEquals(branchStatus, GlobalStatus.Begin);
+        GlobalStatus branchStatus = GlobalStatus.get((byte) BEGIN_CODE);
+        Assertions.assertEquals(branchStatus, GlobalStatus.Begin);
     }
 
     @Test
     public void testGetWithInt() {
         GlobalStatus branchStatus = GlobalStatus.get(BEGIN_CODE);
-        Assert.assertEquals(branchStatus, GlobalStatus.Begin);
+        Assertions.assertEquals(branchStatus, GlobalStatus.Begin);
     }
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test
     public void testGetException() {
-        GlobalStatus.get(NONE);
+        Assertions.assertThrows(IllegalArgumentException.class, () -> GlobalStatus.get(NONE));
     }
 
 }
diff --git a/core/src/test/java/io/seata/core/protocol/MergeResultMessageTest.java b/core/src/test/java/io/seata/core/protocol/MergeResultMessageTest.java
index 33782fa80b051a6bca2664fe9a1f447286a79fbc..8301b7ca7dc8c04a53cc7aa2302d50fa8544d170 100644
--- a/core/src/test/java/io/seata/core/protocol/MergeResultMessageTest.java
+++ b/core/src/test/java/io/seata/core/protocol/MergeResultMessageTest.java
@@ -18,7 +18,7 @@ package io.seata.core.protocol;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.seata.core.protocol.transaction.GlobalBeginResponse;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -83,4 +83,4 @@ public class MergeResultMessageTest {
         return globalBeginResponse;
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/protocol/MergedWarpMessageTest.java b/core/src/test/java/io/seata/core/protocol/MergedWarpMessageTest.java
index 5a5f3d03124d47cd03017d0147af6e31f9cc575e..ee6b9d03dd04c4b41d85145c8f771394b4e5aa7f 100644
--- a/core/src/test/java/io/seata/core/protocol/MergedWarpMessageTest.java
+++ b/core/src/test/java/io/seata/core/protocol/MergedWarpMessageTest.java
@@ -18,7 +18,7 @@ package io.seata.core.protocol;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.seata.core.protocol.transaction.GlobalBeginRequest;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
 
@@ -74,4 +74,4 @@ public class MergedWarpMessageTest {
         globalBeginRequest.setTimeout(3000);
         return globalBeginRequest;
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java b/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java
index 80b228f3878bc3a87b8de0167f0b12cafa092dce..1ffafc89311f62a4ebb27a8648481ce703c66739 100644
--- a/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java
+++ b/core/src/test/java/io/seata/core/protocol/MessageFutureTest.java
@@ -15,16 +15,16 @@
  */
 package io.seata.core.protocol;
 
+import com.alibaba.fastjson.JSON;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import com.alibaba.fastjson.JSON;
-
-import org.junit.Test;
-
 import static org.assertj.core.api.Assertions.assertThat;
 
 /**
@@ -48,15 +48,15 @@ public class MessageFutureTest {
     @Test
     public void testFieldSetGet() {
         String fromJson = "{\n" +
-            "\t\"requestMessage\":{\n" +
-            "\t\t\"async\":" + ASYNC_FIELD + ",\n" +
-            "\t\t\"body\":\"" + BODY_FIELD + "\",\n" +
-            "\t\t\"heartbeat\":" + HEART_BEAT_FIELD + ",\n" +
-            "\t\t\"id\":" + ID_FIELD + ",\n" +
-            "\t\t\"request\":" + REQUEST_FIELD + "\n" +
-            "\t},\n" +
-            "\t\"timeout\":" + TIME_OUT_FIELD + "\n" +
-            "}";
+                "\t\"requestMessage\":{\n" +
+                "\t\t\"async\":" + ASYNC_FIELD + ",\n" +
+                "\t\t\"body\":\"" + BODY_FIELD + "\",\n" +
+                "\t\t\"heartbeat\":" + HEART_BEAT_FIELD + ",\n" +
+                "\t\t\"id\":" + ID_FIELD + ",\n" +
+                "\t\t\"request\":" + REQUEST_FIELD + "\n" +
+                "\t},\n" +
+                "\t\"timeout\":" + TIME_OUT_FIELD + "\n" +
+                "}";
         MessageFuture fromJsonFuture = JSON.parseObject(fromJson, MessageFuture.class);
         assertThat(fromJsonFuture.getTimeout()).isEqualTo(TIME_OUT_FIELD);
         MessageFuture toJsonFuture = new MessageFuture();
@@ -83,56 +83,53 @@ public class MessageFutureTest {
 
     /**
      * Test get no result with time out exception.
-     *
-     * @throws Exception the exception
      */
-    @Test(expected = TimeoutException.class)
-    public void testGetNoResultWithTimeOutException() throws Exception {
-        MessageFuture messageFuture = new MessageFuture();
-        messageFuture.setRequestMessage(buildRepcMessage());
-        messageFuture.setTimeout(TIME_OUT_FIELD);
-        messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+    @Test
+    public void testGetNoResultWithTimeOutException() {
+        Assertions.assertThrows(TimeoutException.class, () -> {
+            MessageFuture messageFuture = new MessageFuture();
+            messageFuture.setRequestMessage(buildRepcMessage());
+            messageFuture.setTimeout(TIME_OUT_FIELD);
+            messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+        });
     }
 
     /**
      * Test get has result with time out exception.
-     *
-     * @throws Exception the exception
      */
-    @Test(expected = TimeoutException.class)
-    public void testGetHasResultWithTimeOutException() throws Exception {
-        MessageFuture messageFuture = new MessageFuture();
-        messageFuture.setRequestMessage(buildRepcMessage());
-        messageFuture.setTimeout(TIME_OUT_FIELD);
-        ExecutorService executorService = Executors.newSingleThreadExecutor();
-        CountDownLatch downLatch = new CountDownLatch(1);
-        executorService.execute(new Runnable() {
-            @Override
-            public void run() {
+    @Test
+    public void testGetHasResultWithTimeOutException() {
+        Assertions.assertThrows(TimeoutException.class, () -> {
+            MessageFuture messageFuture = new MessageFuture();
+            messageFuture.setRequestMessage(buildRepcMessage());
+            messageFuture.setTimeout(TIME_OUT_FIELD);
+            ExecutorService executorService = Executors.newSingleThreadExecutor();
+            CountDownLatch downLatch = new CountDownLatch(1);
+            executorService.execute(() -> {
                 try {
                     downLatch.await();
                     messageFuture.setResultMessage("has_result");
                 } catch (InterruptedException e) {
 
                 }
-            }
+            });
+            messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+            downLatch.countDown();
         });
-        messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
-        downLatch.countDown();
     }
 
     /**
      * Test get has result with run time exception.
-     *
-     * @throws Exception the exception
      */
-    @Test(expected = RuntimeException.class)
-    public void testGetHasResultWithRunTimeException() throws Exception {
-        MessageFuture messageFuture = new MessageFuture();
-        messageFuture.setRequestMessage(buildRepcMessage());
-        messageFuture.setTimeout(TIME_OUT_FIELD);
-        messageFuture.setResultMessage(new RuntimeException());
-        messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+    @Test
+    public void testGetHasResultWithRunTimeException() {
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            MessageFuture messageFuture = new MessageFuture();
+            messageFuture.setRequestMessage(buildRepcMessage());
+            messageFuture.setTimeout(TIME_OUT_FIELD);
+            messageFuture.setResultMessage(new RuntimeException());
+            messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+        });
     }
 
     /**
@@ -156,16 +153,16 @@ public class MessageFutureTest {
 
     /**
      * Test get has result with throwable.
-     *
-     * @throws Exception the exception
      */
-    @Test(expected = RuntimeException.class)
-    public void testGetHasResultWithThrowable() throws Exception {
-        MessageFuture messageFuture = new MessageFuture();
-        messageFuture.setRequestMessage(buildRepcMessage());
-        messageFuture.setTimeout(TIME_OUT_FIELD);
-        messageFuture.setResultMessage(new Throwable());
-        messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+    @Test
+    public void testGetHasResultWithThrowable() {
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            MessageFuture messageFuture = new MessageFuture();
+            messageFuture.setRequestMessage(buildRepcMessage());
+            messageFuture.setTimeout(TIME_OUT_FIELD);
+            messageFuture.setResultMessage(new Throwable());
+            messageFuture.get(TIME_OUT_FIELD, TimeUnit.MILLISECONDS);
+        });
     }
 
     /**
diff --git a/core/src/test/java/io/seata/core/protocol/RegisterRMRequestTest.java b/core/src/test/java/io/seata/core/protocol/RegisterRMRequestTest.java
index d0eb6dee0d581682dc15972146666a79b16852ab..efede6452e9bac0113dcf3d72bfa20c9377762c4 100644
--- a/core/src/test/java/io/seata/core/protocol/RegisterRMRequestTest.java
+++ b/core/src/test/java/io/seata/core/protocol/RegisterRMRequestTest.java
@@ -17,7 +17,7 @@ package io.seata.core.protocol;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -80,4 +80,4 @@ public class RegisterRMRequestTest {
         registerRMRequest.setVersion("1");
         return registerRMRequest;
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java b/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java
index 7c8081effc879b9c1de067f9c960d28850d454c4..180dbcf7efc7feb021ef29efc31cfe02c11a0f77 100644
--- a/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java
+++ b/core/src/test/java/io/seata/core/protocol/RpcMessageTest.java
@@ -17,7 +17,7 @@ package io.seata.core.protocol;
 
 import com.alibaba.fastjson.JSON;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java
index b46fcec16d74a0c793b8b0f3a6112e6e35d790d2..0f77c30ff450a02c1d5959c90b6ecceef2922e5e 100644
--- a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java
+++ b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackRequestTest.java
@@ -19,8 +19,8 @@ package io.seata.core.protocol.transaction;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.UnpooledByteBufAllocator;
 import io.seata.core.model.BranchType;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author: jimin.jm@alibaba-inc.com
@@ -37,7 +37,7 @@ public class BranchRollbackRequestTest {
         branchRollbackRequest.setResourceId("resource1");
         branchRollbackRequest.setApplicationData("app1");
 
-        Assert.assertEquals("xid=127.0.0.1:9999:39875642,branchId=1,branchType=AT,"
+        Assertions.assertEquals("xid=127.0.0.1:9999:39875642,branchId=1,branchType=AT,"
             + "resourceId=resource1,applicationData=app1", branchRollbackRequest.toString());
 
     }
@@ -59,12 +59,12 @@ public class BranchRollbackRequestTest {
 
         BranchRollbackRequest decodeBranchRollbackRequest = new BranchRollbackRequest();
         decodeBranchRollbackRequest.decode(byteBuffer);
-        Assert.assertEquals(decodeBranchRollbackRequest.getXid(), branchRollbackRequest.getXid());
-        Assert.assertEquals(decodeBranchRollbackRequest.getBranchId(), branchRollbackRequest.getBranchId());
-        Assert.assertEquals(decodeBranchRollbackRequest.getResourceId(), branchRollbackRequest.getResourceId());
-        Assert.assertEquals(decodeBranchRollbackRequest.getApplicationData(),
+        Assertions.assertEquals(decodeBranchRollbackRequest.getXid(), branchRollbackRequest.getXid());
+        Assertions.assertEquals(decodeBranchRollbackRequest.getBranchId(), branchRollbackRequest.getBranchId());
+        Assertions.assertEquals(decodeBranchRollbackRequest.getResourceId(), branchRollbackRequest.getResourceId());
+        Assertions.assertEquals(decodeBranchRollbackRequest.getApplicationData(),
             decodeBranchRollbackRequest.getApplicationData());
-        Assert.assertEquals(decodeBranchRollbackRequest.getBranchType(), branchRollbackRequest.getBranchType());
+        Assertions.assertEquals(decodeBranchRollbackRequest.getBranchType(), branchRollbackRequest.getBranchType());
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java
index 410b20a5d279aa8788edfec76e84acdee1f0cae4..9b50e0015de1ab7303c697a4e602efb84c76ce9b 100644
--- a/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java
+++ b/core/src/test/java/io/seata/core/protocol/transaction/BranchRollbackResponseTest.java
@@ -19,8 +19,8 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.UnpooledByteBufAllocator;
 import io.seata.core.model.BranchStatus;
 import io.seata.core.protocol.ResultCode;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author: jimin.jm@alibaba-inc.com
@@ -35,7 +35,7 @@ public class BranchRollbackResponseTest {
         branchRollbackResponse.setBranchStatus(BranchStatus.PhaseOne_Done);
         branchRollbackResponse.setResultCode(ResultCode.Success);
         branchRollbackResponse.setMsg("");
-        Assert.assertEquals(
+        Assertions.assertEquals(
             "xid=127.0.0.1:8091:123456,branchId=2345678,branchStatus=PhaseOne_Done,result code =Success,getMsg =",
             branchRollbackResponse.toString());
 
@@ -57,13 +57,13 @@ public class BranchRollbackResponseTest {
 
         BranchRollbackResponse decodeBranchRollbackResponse = new BranchRollbackResponse();
         decodeBranchRollbackResponse.decode(byteBuffer);
-        Assert.assertEquals(decodeBranchRollbackResponse.getXid(), branchRollbackResponse.getXid());
-        Assert.assertEquals(decodeBranchRollbackResponse.getBranchId(), branchRollbackResponse.getBranchId());
-        Assert.assertEquals(decodeBranchRollbackResponse.getResultCode(), branchRollbackResponse.getResultCode());
-        Assert.assertEquals(decodeBranchRollbackResponse.getBranchStatus(), branchRollbackResponse.getBranchStatus());
-        Assert.assertEquals(decodeBranchRollbackResponse.getTransactionExceptionCode(),
+        Assertions.assertEquals(decodeBranchRollbackResponse.getXid(), branchRollbackResponse.getXid());
+        Assertions.assertEquals(decodeBranchRollbackResponse.getBranchId(), branchRollbackResponse.getBranchId());
+        Assertions.assertEquals(decodeBranchRollbackResponse.getResultCode(), branchRollbackResponse.getResultCode());
+        Assertions.assertEquals(decodeBranchRollbackResponse.getBranchStatus(), branchRollbackResponse.getBranchStatus());
+        Assertions.assertEquals(decodeBranchRollbackResponse.getTransactionExceptionCode(),
             branchRollbackResponse.getTransactionExceptionCode());
-        Assert.assertEquals(decodeBranchRollbackResponse.getMsg(), branchRollbackResponse.getMsg());
+        Assertions.assertEquals(decodeBranchRollbackResponse.getMsg(), branchRollbackResponse.getMsg());
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/protocol/transaction/GlobalBeginResponseTest.java b/core/src/test/java/io/seata/core/protocol/transaction/GlobalBeginResponseTest.java
index 36a26a6df215990370ef7bcd575860c128bad768..beb7bcac9c4f5cab306297e56b49b327659ea451 100644
--- a/core/src/test/java/io/seata/core/protocol/transaction/GlobalBeginResponseTest.java
+++ b/core/src/test/java/io/seata/core/protocol/transaction/GlobalBeginResponseTest.java
@@ -16,8 +16,8 @@
 package io.seata.core.protocol.transaction;
 
 import io.seata.core.protocol.ResultCode;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 import java.nio.ByteBuffer;
 
@@ -38,20 +38,20 @@ public class GlobalBeginResponseTest {
     public void testGetSetXid() {
         GlobalBeginResponse globalBeginResponse = new GlobalBeginResponse();
         globalBeginResponse.setXid(XID);
-        Assert.assertEquals(XID, globalBeginResponse.getXid());
+        Assertions.assertEquals(XID, globalBeginResponse.getXid());
     }
 
     @Test
     public void testGetSetExtraData() {
         GlobalBeginResponse globalBeginResponse = new GlobalBeginResponse();
         globalBeginResponse.setExtraData(EXTRA_DATA);
-        Assert.assertEquals(EXTRA_DATA, globalBeginResponse.getExtraData());
+        Assertions.assertEquals(EXTRA_DATA, globalBeginResponse.getExtraData());
     }
 
     @Test
     public void testGetTypeCode() {
         GlobalBeginResponse globalBeginResponse = new GlobalBeginResponse();
-        Assert.assertEquals(GlobalBeginResponse.TYPE_GLOBAL_BEGIN_RESULT, globalBeginResponse.getTypeCode());
+        Assertions.assertEquals(GlobalBeginResponse.TYPE_GLOBAL_BEGIN_RESULT, globalBeginResponse.getTypeCode());
     }
 
     @Test
diff --git a/core/src/test/java/io/seata/core/rpc/RpcContextTest.java b/core/src/test/java/io/seata/core/rpc/RpcContextTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..92fefa2a4078b893328fb7e931d95dcff7b79a7e
--- /dev/null
+++ b/core/src/test/java/io/seata/core/rpc/RpcContextTest.java
@@ -0,0 +1,186 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.core.rpc;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import java.util.HashSet;
+
+/**
+ * RpcContext Test
+ * 
+ * @author kaitithoma
+ * @author Danaykap
+ * 
+ * @date 2019/ 3/31
+ *
+ */
+
+public class RpcContextTest {
+	/** RpcContext constructor parameter set as constant **/
+	private static RpcContext rpcContext;
+	/** Version value **/
+	private static final String VERSION = "a";
+	/** TransactionServiceGroup value **/
+	private static final String TSG = "a"; 
+	/** ID value for every method needing an Id **/
+	private static final String ID = "1"; 
+	/** ResourceValue value **/
+	private static final String RV = "abc";
+	/** ResourceSet value **/
+	private static final String RS = "b"; 
+
+	/**
+	 * RpcContext Constructor
+	 */
+
+	@BeforeAll
+	public static void setup() {
+		rpcContext = new RpcContext();
+	}
+
+	/**
+	 * Test set ApplicationId to value = "1" Test get ApplicationId
+	 */
+	@Test
+	public void testApplicationIdValue() {
+		rpcContext.setApplicationId(ID);
+		Assertions.assertEquals(ID, rpcContext.getApplicationId());
+	}
+
+	/**
+	 * Test set Version to value = "a" Test get Version
+	 */
+	@Test
+	public void testVersionValue() {
+		rpcContext.setVersion(VERSION);
+		Assertions.assertEquals(VERSION, rpcContext.getVersion());
+	}
+
+	/**
+	 * Test set ClientId to value = "1" Test get ClientId
+	 */
+	@Test
+	public void testClientIdValue() {
+		rpcContext.setClientId(ID);
+		Assertions.assertEquals(ID, rpcContext.getClientId());
+	}
+
+	/**
+	 * Test set Channel to null Test get Channel
+	 */
+	@Test
+	public void testChannelNull() {
+		rpcContext.setChannel(null);
+		Assertions.assertNull(rpcContext.getChannel());
+	}
+
+	/**
+	 * Test set TransactionServiceGroup to value = "1" Test get
+	 * TransactionServiceGroup
+	 */
+	@Test
+	public void testTransactionServiceGroupValue() {
+		rpcContext.setTransactionServiceGroup(TSG);
+		Assertions.assertEquals(TSG, rpcContext.getTransactionServiceGroup());
+	}
+
+	/**
+	 * Test setClientRole to null Test getApplication Id
+	 */
+	@Test
+	public void testClientRoleNull() {
+		rpcContext.setClientRole(null);
+		Assertions.assertNull(rpcContext.getClientRole());
+	}
+
+	/**
+	 * Test set ResourceSets to null Test get ResourceSets
+	 */
+	@Test
+	public void testResourceSetsNull() {
+		rpcContext.setResourceSets(null);
+		Assertions.assertNull(rpcContext.getResourceSets());
+	}
+
+	/**
+	 * Test add resourceSet = null with addResource Test get ResourceSets
+	 */
+	@Test
+	public void testAddResourceNull() {
+		rpcContext.addResource(null);
+		HashSet<String> resourceSet = new HashSet<String>();
+		resourceSet.add(null);
+		Assertions.assertEquals(resourceSet, rpcContext.getResourceSets());
+	}
+
+	/**
+	 * Test add null parameter to ResourceSets with addResources Test get
+	 * ResourceSets
+	 */
+	@Test
+	public void testAddResourcesNull() {
+		rpcContext.addResources(null);
+		rpcContext.setResourceSets(null);
+		Assertions.assertNull(rpcContext.getResourceSets());
+	}
+
+	/**
+	 * Test add a short resourceSet(["abc"]) with addResources Test get ResourceSets
+	 */
+	@Test
+	public void testAddResourcesResourceValue() {
+		HashSet<String> resourceSet = new HashSet<String>();
+		resourceSet.add(RV);
+		rpcContext.addResources(resourceSet);
+		Assertions.assertEquals(resourceSet, rpcContext.getResourceSets());
+	}
+
+	/**
+	 * Test add resource and resource sets to ResourceSets with addResourceSets Test
+	 * getResourceSets
+	 */
+	@Test
+	public void testAddResourcesResourceSetValue() {
+		HashSet<String> resourceSets = new HashSet<String>();
+		resourceSets.add(RS);
+		HashSet<String> resourceSet = new HashSet<String>();
+		resourceSet.add(RV);
+		rpcContext.addResources(resourceSet);
+		rpcContext.setResourceSets(resourceSets);
+		rpcContext.addResources(resourceSet);
+		Assertions.assertEquals(resourceSets, rpcContext.getResourceSets());
+	}
+
+	/**
+	 * Test toString having all the parameters initialized to null
+	 */
+	@Test
+	public void testToString() {
+		rpcContext.setApplicationId(null);
+		rpcContext.setTransactionServiceGroup(null);
+		rpcContext.setClientId(null);
+		rpcContext.setChannel(null);
+		rpcContext.setResourceSets(null);
+		Assertions.assertEquals(
+				"RpcContext{" + "applicationId='" + rpcContext.getApplicationId() + '\'' + ", transactionServiceGroup='"
+						+ rpcContext.getTransactionServiceGroup() + '\'' + ", clientId='" + rpcContext.getClientId() + '\''
+						+ ", channel=" + rpcContext.getChannel() + ", resourceSets=" + rpcContext.getResourceSets() + '}',
+						rpcContext.toString());
+	}
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/io/seata/core/rpc/netty/NettyBaseConfigTest.java b/core/src/test/java/io/seata/core/rpc/netty/NettyBaseConfigTest.java
index 758715293c21ccb14fa43d285dde749d4c85b079..d1faf93584d9000a4035eb4837454dfb37137a5b 100644
--- a/core/src/test/java/io/seata/core/rpc/netty/NettyBaseConfigTest.java
+++ b/core/src/test/java/io/seata/core/rpc/netty/NettyBaseConfigTest.java
@@ -15,7 +15,7 @@
  */
 package io.seata.core.rpc.netty;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Netty base config test.
@@ -32,4 +32,4 @@ public class NettyBaseConfigTest {
         NettyBaseConfig nettyBaseConfig = new NettyBaseConfig();
         System.out.print("test static .");
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/rpc/netty/NettyPoolKeyTest.java b/core/src/test/java/io/seata/core/rpc/netty/NettyPoolKeyTest.java
index 570fbfb543267b46f285abf0fb5fe2525d248a6a..66dc03205e360a5a9770cea75235c11fa4f58a04 100644
--- a/core/src/test/java/io/seata/core/rpc/netty/NettyPoolKeyTest.java
+++ b/core/src/test/java/io/seata/core/rpc/netty/NettyPoolKeyTest.java
@@ -16,11 +16,9 @@
 package io.seata.core.rpc.netty;
 
 import io.seata.core.protocol.RegisterRMRequest;
-import io.seata.core.rpc.netty.NettyPoolKey.TransactionRole;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author: jimin.jm@alibaba-inc.com
@@ -36,47 +34,47 @@ public class NettyPoolKeyTest {
     private static final RegisterRMRequest MSG1 = new RegisterRMRequest("applicationId1", "transactionServiceGroup1");
     private static final RegisterRMRequest MSG2 = new RegisterRMRequest("applicationId2", "transactionServiceGroup2");
 
-    @Before
+    @BeforeEach
     public void init() {
         nettyPoolKey = new NettyPoolKey(RM_ROLE, ADDRESS1, MSG1);
     }
 
     @Test
     public void getTransactionRole() {
-        Assert.assertEquals(nettyPoolKey.getTransactionRole(), RM_ROLE);
+        Assertions.assertEquals(nettyPoolKey.getTransactionRole(), RM_ROLE);
     }
 
     @Test
     public void setTransactionRole() {
         nettyPoolKey.setTransactionRole(TM_ROLE);
-        Assert.assertEquals(nettyPoolKey.getTransactionRole(), TM_ROLE);
+        Assertions.assertEquals(nettyPoolKey.getTransactionRole(), TM_ROLE);
     }
 
     @Test
     public void getAddress() {
-        Assert.assertEquals(nettyPoolKey.getAddress(), ADDRESS1);
+        Assertions.assertEquals(nettyPoolKey.getAddress(), ADDRESS1);
     }
 
     @Test
     public void setAddress() {
         nettyPoolKey.setAddress(ADDRESS2);
-        Assert.assertEquals(nettyPoolKey.getAddress(), ADDRESS2);
+        Assertions.assertEquals(nettyPoolKey.getAddress(), ADDRESS2);
     }
 
     @Test
     public void getMessage() {
-        Assert.assertEquals(nettyPoolKey.getMessage(), MSG1);
+        Assertions.assertEquals(nettyPoolKey.getMessage(), MSG1);
     }
 
     @Test
     public void setMessage() {
         nettyPoolKey.setMessage(MSG2);
-        Assert.assertEquals(nettyPoolKey.getMessage(), MSG2);
+        Assertions.assertEquals(nettyPoolKey.getMessage(), MSG2);
     }
 
     @Test
     public void testToString() {
         String expectStr = "transactionRole:RMROLE,address:127.0.0.1:8091,msg:< " + MSG1.toString() + " >";
-        Assert.assertEquals(nettyPoolKey.toString(), expectStr);
+        Assertions.assertEquals(nettyPoolKey.toString(), expectStr);
     }
-}
\ No newline at end of file
+}
diff --git a/core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java b/core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java
index 2fdb4721c6e82458e28da403241192eced0e91d8..7a6169d1416e6868fc5e9179cdecc7717c0b17e4 100644
--- a/core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java
+++ b/core/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java
@@ -27,8 +27,8 @@ import io.netty.channel.Channel;
 import io.netty.channel.ChannelOption;
 import io.netty.channel.socket.nio.NioSocketChannel;
 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Tm rpc client test.
@@ -55,12 +55,12 @@ public class TmRpcClientTest {
 
         NettyClientConfig defaultNettyClientConfig = new NettyClientConfig();
         GenericKeyedObjectPool.Config config = tmRpcClient.getNettyPoolConfig();
-        Assert.assertEquals(defaultNettyClientConfig.getMaxPoolActive(), config.maxActive);
-        Assert.assertEquals(defaultNettyClientConfig.getMinPoolIdle(), config.minIdle);
-        Assert.assertEquals(defaultNettyClientConfig.getMaxAcquireConnMills(), config.maxWait);
-        Assert.assertEquals(defaultNettyClientConfig.isPoolTestBorrow(), config.testOnBorrow);
-        Assert.assertEquals(defaultNettyClientConfig.isPoolTestReturn(), config.testOnReturn);
-        Assert.assertEquals(defaultNettyClientConfig.isPoolLifo(), config.lifo);
+        Assertions.assertEquals(defaultNettyClientConfig.getMaxPoolActive(), config.maxActive);
+        Assertions.assertEquals(defaultNettyClientConfig.getMinPoolIdle(), config.minIdle);
+        Assertions.assertEquals(defaultNettyClientConfig.getMaxAcquireConnMills(), config.maxWait);
+        Assertions.assertEquals(defaultNettyClientConfig.isPoolTestBorrow(), config.testOnBorrow);
+        Assertions.assertEquals(defaultNettyClientConfig.isPoolTestReturn(), config.testOnReturn);
+        Assertions.assertEquals(defaultNettyClientConfig.isPoolLifo(), config.lifo);
     }
 
     /**
@@ -81,22 +81,22 @@ public class TmRpcClientTest {
         bootstrapField.setAccessible(true);
         Bootstrap bootstrap = (Bootstrap)bootstrapField.get(tmRpcClient);
 
-        Assert.assertNotNull(bootstrap);
+        Assertions.assertNotNull(bootstrap);
         Field optionsField = getDeclaredField(bootstrap, "options");
         optionsField.setAccessible(true);
         Map<ChannelOption<?>, Object> options = (Map<ChannelOption<?>, Object>)optionsField.get(bootstrap);
-        Assert.assertTrue(Boolean.TRUE.equals(options.get(ChannelOption.TCP_NODELAY)));
-        Assert.assertTrue(Boolean.TRUE.equals(options.get(ChannelOption.SO_KEEPALIVE)));
-        Assert.assertEquals(10000, options.get(ChannelOption.CONNECT_TIMEOUT_MILLIS));
-        Assert.assertTrue(Boolean.TRUE.equals(options.get(ChannelOption.SO_KEEPALIVE)));
-        Assert.assertEquals(153600, options.get(ChannelOption.SO_RCVBUF));
+        Assertions.assertTrue(Boolean.TRUE.equals(options.get(ChannelOption.TCP_NODELAY)));
+        Assertions.assertTrue(Boolean.TRUE.equals(options.get(ChannelOption.SO_KEEPALIVE)));
+        Assertions.assertEquals(10000, options.get(ChannelOption.CONNECT_TIMEOUT_MILLIS));
+        Assertions.assertTrue(Boolean.TRUE.equals(options.get(ChannelOption.SO_KEEPALIVE)));
+        Assertions.assertEquals(153600, options.get(ChannelOption.SO_RCVBUF));
 
         Field channelFactoryField = getDeclaredField(bootstrap, "channelFactory");
         channelFactoryField.setAccessible(true);
         ChannelFactory<? extends Channel>
             channelFactory = (ChannelFactory<? extends Channel>)channelFactoryField.get(bootstrap);
-        Assert.assertNotNull(channelFactory);
-        Assert.assertTrue(channelFactory.newChannel() instanceof NioSocketChannel);
+        Assertions.assertNotNull(channelFactory);
+        Assertions.assertTrue(channelFactory.newChannel() instanceof NioSocketChannel);
 
     }
 
diff --git a/discovery/pom.xml b/discovery/pom.xml
index af586b5ec5070f019a5a07e250e33b57791a9328..1e0d83b168486c4cc21f019f1d65e35ce37f5774 100644
--- a/discovery/pom.xml
+++ b/discovery/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -38,17 +38,4 @@
         <module>seata-discovery-etcd3</module>
         <module>seata-discovery-sofa</module>
     </modules>
-
-    <dependencies>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
 </project>
diff --git a/discovery/seata-discovery-all/pom.xml b/discovery/seata-discovery-all/pom.xml
index 598649d8273025c85b1d41ee792350a34c808de7..31774f5521571b6e39aa37c7eb2e655ed34e41ba 100644
--- a/discovery/seata-discovery-all/pom.xml
+++ b/discovery/seata-discovery-all/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -29,30 +29,37 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-consul</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-eureka</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-zk</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-redis</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-nacos</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-etcd3</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-sofa</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/discovery/seata-discovery-consul/pom.xml b/discovery/seata-discovery-consul/pom.xml
index 357579bb9a40f3713ab58ca5faecdd1fa7275190..9c01530d9e24a670b59a9945b78d994f05b14117 100644
--- a/discovery/seata-discovery-consul/pom.xml
+++ b/discovery/seata-discovery-consul/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -35,5 +35,13 @@
             <groupId>com.ecwid.consul</groupId>
             <artifactId>consul-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/discovery/seata-discovery-consul/src/test/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImplTest.java b/discovery/seata-discovery-consul/src/test/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImplTest.java
index f1e0914526377407fcd2436899704912b3f2d168..08ba4ad5b2d4b7ff0d6a92a952548a6b08274c0e 100644
--- a/discovery/seata-discovery-consul/src/test/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImplTest.java
+++ b/discovery/seata-discovery-consul/src/test/java/io/seata/discovery/registry/consul/ConsulRegistryServiceImplTest.java
@@ -16,11 +16,10 @@
 package io.seata.discovery.registry.consul;
 
 import io.seata.discovery.registry.RegistryService;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.net.InetSocketAddress;
 
-import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
diff --git a/discovery/seata-discovery-core/pom.xml b/discovery/seata-discovery-core/pom.xml
index 722ea5ecec4ff1bd6244cef439823c12cdeb8361..bafd01187aab615ffd6007ce278bb6e54873ec6f 100644
--- a/discovery/seata-discovery-core/pom.xml
+++ b/discovery/seata-discovery-core/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-config-core</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/discovery/seata-discovery-core/src/main/resources/META-INF/services/io.seata.discovery.loadbalance.LoadBalance b/discovery/seata-discovery-core/src/main/resources/META-INF/services/io.seata.discovery.loadbalance.LoadBalance
index e22cb66c9d50a26060dc1a80416d34e3926b298b..7209468487212974d19c72fadbac433142fd3cd2 100644
--- a/discovery/seata-discovery-core/src/main/resources/META-INF/services/io.seata.discovery.loadbalance.LoadBalance
+++ b/discovery/seata-discovery-core/src/main/resources/META-INF/services/io.seata.discovery.loadbalance.LoadBalance
@@ -1,5 +1,5 @@
 #
-#  Copyright 1999-2018 Alibaba Group Holding Ltd.
+#  Copyright 1999-2019 Seata.io Group.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
 #
 
 #
-#  Copyright 1999-2018 Alibaba Group Holding Ltd.
+#  Copyright 1999-2019 Seata.io Group.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@
 #
 
 #
-#  Copyright 1999-2018 Alibaba Group Holding Ltd.
+#  Copyright 1999-2019 Seata.io Group.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceFactoryTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceFactoryTest.java
index e73d91406cb3d5cb1b3fb544085fd50faa4c4a67..0f777a3d081b316c6cef4f173a173a27bc69d9f3 100644
--- a/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceFactoryTest.java
+++ b/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceFactoryTest.java
@@ -15,18 +15,19 @@
  */
 package io.seata.discovery.loadbalance;
 
+import io.seata.discovery.registry.RegistryFactory;
+import io.seata.discovery.registry.RegistryService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
-
-import io.seata.discovery.registry.RegistryFactory;
-import io.seata.discovery.registry.RegistryService;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.stream.Stream;
 
 /**
  * The type Load balance factory test.
@@ -42,10 +43,11 @@ public class LoadBalanceFactoryTest {
      * @param loadBalance the load balance
      * @throws Exception the exception
      */
-    @Test(dataProvider = "instanceProvider")
-    @Ignore
+    @ParameterizedTest
+    @MethodSource("instanceProvider")
+    @Disabled
     public void testGetRegistry(LoadBalance loadBalance) throws Exception {
-        Assert.assertNotNull(loadBalance);
+        Assertions.assertNotNull(loadBalance);
         RegistryService registryService = RegistryFactory.getInstance();
         InetSocketAddress address1 = new InetSocketAddress("127.0.0.1", 8091);
         InetSocketAddress address2 = new InetSocketAddress("127.0.0.1", 8092);
@@ -53,7 +55,7 @@ public class LoadBalanceFactoryTest {
         registryService.register(address2);
         List<InetSocketAddress> addressList = registryService.lookup("my_test_tx_group");
         InetSocketAddress balanceAddress = loadBalance.select(addressList);
-        Assert.assertNotNull(balanceAddress);
+        Assertions.assertNotNull(balanceAddress);
     }
 
     /**
@@ -62,9 +64,10 @@ public class LoadBalanceFactoryTest {
      * @param loadBalance the load balance
      * @throws Exception the exception
      */
-    @Test
-    @Ignore
-    public void testUnRegistry() throws Exception {
+    @ParameterizedTest
+    @MethodSource("instanceProvider")
+    @Disabled
+    public void testUnRegistry(LoadBalance loadBalance) throws Exception {
         RegistryService registryService = RegistryFactory.getInstance();
         InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8091);
         registryService.unregister(address);
@@ -76,10 +79,11 @@ public class LoadBalanceFactoryTest {
      * @param loadBalance the load balance
      * @throws Exception the exception
      */
-    @Test(dataProvider = "instanceProvider")
-    @Ignore
+    @ParameterizedTest
+    @MethodSource("instanceProvider")
+    @Disabled
     public void testSubscribe(LoadBalance loadBalance) throws Exception {
-        Assert.assertNotNull(loadBalance);
+        Assertions.assertNotNull(loadBalance);
         RegistryService registryService = RegistryFactory.getInstance();
         InetSocketAddress address1 = new InetSocketAddress("127.0.0.1", 8091);
         InetSocketAddress address2 = new InetSocketAddress("127.0.0.1", 8092);
@@ -87,10 +91,10 @@ public class LoadBalanceFactoryTest {
         registryService.register(address2);
         List<InetSocketAddress> addressList = registryService.lookup("my_test_tx_group");
         InetSocketAddress balanceAddress = loadBalance.select(addressList);
-        Assert.assertNotNull(balanceAddress);
+        Assertions.assertNotNull(balanceAddress);
         TimeUnit.SECONDS.sleep(30);//等待testUnRegistry事件触发
         List<InetSocketAddress> addressList1 = registryService.lookup("my_test_tx_group");
-        Assert.assertEquals(1, addressList1.size());
+        Assertions.assertEquals(1, addressList1.size());
     }
 
     /**
@@ -99,14 +103,15 @@ public class LoadBalanceFactoryTest {
      * @param loadBalance the load balance
      * @throws Exception the exception
      */
-    @Test(dataProvider = "instanceProvider")
+    @ParameterizedTest
+    @MethodSource("instanceProvider")
     public void testGetAddress(LoadBalance loadBalance) throws Exception {
-        Assert.assertNotNull(loadBalance);
+        Assertions.assertNotNull(loadBalance);
         InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8091);
         List<InetSocketAddress> addressList = new ArrayList<>();
         addressList.add(address);
         InetSocketAddress balanceAddress = loadBalance.select(addressList);
-        Assert.assertEquals(address, balanceAddress);
+        Assertions.assertEquals(address, balanceAddress);
     }
 
     /**
@@ -114,10 +119,10 @@ public class LoadBalanceFactoryTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] instanceProvider() {
+    static Stream<Arguments> instanceProvider() {
         LoadBalance loadBalance = LoadBalanceFactory.getInstance();
-        return new Object[][] {{loadBalance}};
+        return Stream.of(
+                Arguments.of(loadBalance)
+        );
     }
-
-}
\ No newline at end of file
+}
diff --git a/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceTest.java b/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceTest.java
index b4b6ebd0dba574b663c398f27b8361883f6c99b0..d9c9f64792a22d993ba9f1932b0a2d6b863b4bc3 100644
--- a/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceTest.java
+++ b/discovery/seata-discovery-core/src/test/java/io/seata/discovery/loadbalance/LoadBalanceTest.java
@@ -15,16 +15,17 @@
  */
 package io.seata.discovery.loadbalance;
 
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
 import java.net.InetSocketAddress;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
-
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-import org.testng.collections.Lists;
+import java.util.stream.Stream;
 
 /**
  * Created by guoyao on 2019/2/14.
@@ -36,13 +37,14 @@ public class LoadBalanceTest {
      *
      * @param addresses the addresses
      */
-    @Test(dataProvider = "addressProvider")
+    @ParameterizedTest
+    @MethodSource("addressProvider")
     public void testRandomLoadBalance_select(List<InetSocketAddress> addresses) {
         int runs = 10000;
         Map<InetSocketAddress, AtomicLong> counter = getSelectedCounter(runs, addresses, new RandomLoadBalance());
         for (InetSocketAddress address : counter.keySet()) {
             Long count = counter.get(address).get();
-            Assert.assertTrue(count > 0, "selecte one time at last");
+            Assertions.assertTrue(count > 0, "selecte one time at last");
         }
     }
 
@@ -51,13 +53,14 @@ public class LoadBalanceTest {
      *
      * @param addresses the addresses
      */
-    @Test(dataProvider = "addressProvider")
+    @ParameterizedTest
+    @MethodSource("addressProvider")
     public void testRoundRobinLoadBalance_select(List<InetSocketAddress> addresses) {
         int runs = 10000;
         Map<InetSocketAddress, AtomicLong> counter = getSelectedCounter(runs, addresses, new RoundRobinLoadBalance());
         for (InetSocketAddress address : counter.keySet()) {
             Long count = counter.get(address).get();
-            Assert.assertTrue(Math.abs(count - runs / (0f + addresses.size())) < 1f, "abs diff shoud < 1");
+            Assertions.assertTrue(Math.abs(count - runs / (0f + addresses.size())) < 1f, "abs diff shoud < 1");
         }
     }
 
@@ -71,7 +74,7 @@ public class LoadBalanceTest {
      */
     public Map<InetSocketAddress, AtomicLong> getSelectedCounter(int runs, List<InetSocketAddress> addresses,
                                                                  LoadBalance loadBalance) {
-        Assert.assertNotNull(loadBalance);
+        Assertions.assertNotNull(loadBalance);
         Map<InetSocketAddress, AtomicLong> counter = new ConcurrentHashMap<>();
         for (InetSocketAddress address : addresses) {
             counter.put(address, new AtomicLong(0));
@@ -90,17 +93,15 @@ public class LoadBalanceTest {
     /**
      * Address provider object [ ] [ ].
      *
-     * @return the object [ ] [ ]
+     * @return Stream<List < InetSocketAddress>>
      */
-    @DataProvider
-    public static Object[][] addressProvider() {
-        List<InetSocketAddress> addresses = Lists.newArrayList();
-        addresses.add(new InetSocketAddress("127.0.0.1", 8091));
-        addresses.add(new InetSocketAddress("127.0.0.1", 8092));
-        addresses.add(new InetSocketAddress("127.0.0.1", 8093));
-        addresses.add(new InetSocketAddress("127.0.0.1", 8094));
-        addresses.add(new InetSocketAddress("127.0.0.1", 8095));
-        return new Object[][] {{addresses}};
+    static Stream<List<InetSocketAddress>> addressProvider() {
+        return Stream.of(
+                Arrays.asList(new InetSocketAddress("127.0.0.1", 8091),
+                        new InetSocketAddress("127.0.0.1", 8092),
+                        new InetSocketAddress("127.0.0.1", 8093),
+                        new InetSocketAddress("127.0.0.1", 8094),
+                        new InetSocketAddress("127.0.0.1", 8095))
+        );
     }
-
 }
diff --git a/discovery/seata-discovery-core/src/test/java/resources/apollo.properties b/discovery/seata-discovery-core/src/test/resources/apollo.properties
similarity index 100%
rename from discovery/seata-discovery-core/src/test/java/resources/apollo.properties
rename to discovery/seata-discovery-core/src/test/resources/apollo.properties
diff --git a/discovery/seata-discovery-etcd3/pom.xml b/discovery/seata-discovery-etcd3/pom.xml
index 014c5258480f24e923fdeb3869c0f0f1aa9f9cee..892290a2fb2a26658cbab56a10fcc80ed63ad44f 100644
--- a/discovery/seata-discovery-etcd3/pom.xml
+++ b/discovery/seata-discovery-etcd3/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@
 
     <dependencies>
         <dependency>
-            <groupId>io.seata</groupId>
+            <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-core</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
diff --git a/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryProviderTest.java b/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryProviderTest.java
index da6813dc4864725dceb34a36f0db8d83cca17ec5..90ea08ed8b8ab9266c722e72efe50cb8ce48e55b 100644
--- a/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryProviderTest.java
+++ b/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryProviderTest.java
@@ -17,7 +17,7 @@ package io.seata.discovery.registry.etcd;
 
 import io.seata.discovery.registery.etcd.EtcdRegistryProvider;
 import io.seata.discovery.registery.etcd.EtcdRegistryServiceImpl;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryServiceImplTest.java b/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryServiceImplTest.java
index d126319febd6c71aaf161c3b05140207f0cdc3a6..3c2346a1ea3d6391bdc4052fe58492a69a633cbb 100644
--- a/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryServiceImplTest.java
+++ b/discovery/seata-discovery-etcd3/src/test/java/io/seata/discovery/registry/etcd/EtcdRegistryServiceImplTest.java
@@ -25,10 +25,11 @@ import io.etcd.jetcd.watch.WatchResponse;
 import io.seata.discovery.registery.etcd.EtcdRegistryProvider;
 import io.seata.discovery.registery.etcd.EtcdRegistryServiceImpl;
 import io.seata.discovery.registry.RegistryService;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 import java.net.InetSocketAddress;
 import java.util.List;
@@ -41,23 +42,24 @@ import static org.assertj.core.api.Assertions.assertThat;
  * @author xingfudeshi@gmail.com
  * @date 2019/04/26
  */
+@Disabled
 public class EtcdRegistryServiceImplTest {
     private static final String REGISTRY_KEY_PREFIX = "registry-seata-";
     private static final String CLUSTER_NAME = "default";
     @Rule
-    private final EtcdClusterResource etcd = new EtcdClusterResource(CLUSTER_NAME, 1);
+    private final static EtcdClusterResource etcd = new EtcdClusterResource(CLUSTER_NAME, 1);
 
     private final Client client = Client.builder().endpoints(etcd.cluster().getClientEndpoints()).build();
     private final static String HOST = "127.0.0.1";
     private final static int PORT = 8091;
 
-    @BeforeClass
-    public void beforeClass() throws Exception {
+    @BeforeAll
+    public static void beforeClass() throws Exception {
         System.setProperty(EtcdRegistryServiceImpl.TEST_ENDPONT, etcd.cluster().getClientEndpoints().get(0).toString());
     }
 
-    @AfterClass
-    public void afterClass() throws Exception {
+    @AfterAll
+    public static void afterClass() throws Exception {
         System.setProperty(EtcdRegistryServiceImpl.TEST_ENDPONT, "");
     }
 
diff --git a/discovery/seata-discovery-eureka/pom.xml b/discovery/seata-discovery-eureka/pom.xml
index 559b46bf2754040409474f509e73c3ff12ed42e0..99c7a8d31e96da6e787278ce5a296936b6a425ab 100644
--- a/discovery/seata-discovery-eureka/pom.xml
+++ b/discovery/seata-discovery-eureka/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/discovery/seata-discovery-nacos/pom.xml b/discovery/seata-discovery-nacos/pom.xml
index cb3f0e3bc9946a020d250be08f8f243092db644b..39093c0113a322ed5ce3138ed6753f567d526fa3 100644
--- a/discovery/seata-discovery-nacos/pom.xml
+++ b/discovery/seata-discovery-nacos/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/discovery/seata-discovery-redis/pom.xml b/discovery/seata-discovery-redis/pom.xml
index 2215382d302f23b9e6e2cec8a870ea1f29a0f8e8..d743921867ebda2a2cdc1bbb087e20743ce8dc53 100644
--- a/discovery/seata-discovery-redis/pom.xml
+++ b/discovery/seata-discovery-redis/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/discovery/seata-discovery-sofa/pom.xml b/discovery/seata-discovery-sofa/pom.xml
index dcd620e16020fb4b9485952a3e92e29256d82d2f..a3d7221d320e97a1aa7fa7fa8b5f9dfc84fc1804 100644
--- a/discovery/seata-discovery-sofa/pom.xml
+++ b/discovery/seata-discovery-sofa/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -32,38 +32,13 @@
             <version>${project.parent.version}</version>
         </dependency>
          <dependency>
-                <groupId>com.alipay.sofa</groupId>
-                <artifactId>registry-client-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>registry-client-all</artifactId>
         </dependency>
-
         <dependency>
             <groupId>com.alipay.sofa</groupId>
             <artifactId>registry-test</artifactId>
-            <version>${sofa.registry.version}</version>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <artifactId>log4j-over-slf4j</artifactId>
-                    <groupId>org.slf4j</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>log4j-jcl</artifactId>
-                    <groupId>org.apache.logging.log4j</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>log4j-core</artifactId>
-                    <groupId>org.apache.logging.log4j</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>log4j-api</artifactId>
-                    <groupId>org.apache.logging.log4j</groupId>
-                </exclusion>
-            </exclusions>
         </dependency>
     </dependencies>
 </project>
diff --git a/discovery/seata-discovery-sofa/src/test/io/seata/discovery/registry/sofa/SofaRegistryServiceImplTest.java b/discovery/seata-discovery-sofa/src/test/io/seata/discovery/registry/sofa/SofaRegistryServiceImplTest.java
index 4a5e1b6a691076f296d03804b6eb4afaacf62b2d..9fae112de87e6f325e2b1bd67ebfb14e94d7a54c 100644
--- a/discovery/seata-discovery-sofa/src/test/io/seata/discovery/registry/sofa/SofaRegistryServiceImplTest.java
+++ b/discovery/seata-discovery-sofa/src/test/io/seata/discovery/registry/sofa/SofaRegistryServiceImplTest.java
@@ -16,10 +16,10 @@
 package io.seata.discovery.registry.sofa;
 
 import com.alipay.sofa.registry.server.test.TestRegistryMain;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
 
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
@@ -34,7 +34,7 @@ public class SofaRegistryServiceImplTest {
 
     private static TestRegistryMain registryMain;
 
-    @BeforeClass
+    @BeforeAll
     public static void beforeClass() {
         System.setProperty("serverAddr", "127.0.0.1:9603");
         System.setProperty("addressWaitTime", "10000");
@@ -42,7 +42,7 @@ public class SofaRegistryServiceImplTest {
         try {
             registryMain.startRegistry();
         } catch (Exception e) {
-            Assert.fail("start sofaregistry fail");
+            Assertions.fail("start sofaregistry fail");
         }
     }
 
@@ -54,7 +54,7 @@ public class SofaRegistryServiceImplTest {
         try {
             instance.register(address);
         } catch (Exception e) {
-            Assert.fail(e.getMessage());
+            Assertions.fail(e.getMessage());
         }
 
         //need sofa registry to sync data
@@ -67,17 +67,17 @@ public class SofaRegistryServiceImplTest {
         try {
             result = instance.lookup("my_test_tx_group");
         } catch (Exception e) {
-            Assert.fail(e.getMessage());
+            Assertions.fail(e.getMessage());
         }
 
-        Assert.assertTrue(result.size() > 0);
-        Assert.assertEquals(address, result.get(0));
+        Assertions.assertTrue(result.size() > 0);
+        Assertions.assertEquals(address, result.get(0));
 
 
         try {
             instance.unregister(address);
         } catch (Exception e) {
-            Assert.fail(e.getMessage());
+            Assertions.fail(e.getMessage());
         }
 
         try {
@@ -88,15 +88,15 @@ public class SofaRegistryServiceImplTest {
         try {
             result = instance.lookup("my_test_tx_group");
         } catch (Exception e) {
-            Assert.fail(e.getMessage());
+            Assertions.fail(e.getMessage());
         }
 
-        Assert.assertEquals(0, result.size());
+        Assertions.assertEquals(0, result.size());
 
     }
 
 
-    @AfterClass
+    @AfterAll
     public static void afterClass() {
         System.setProperty("serverAddr", "");
         System.setProperty("addressWaitTime", "0");
@@ -109,4 +109,4 @@ public class SofaRegistryServiceImplTest {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/discovery/seata-discovery-zk/pom.xml b/discovery/seata-discovery-zk/pom.xml
index 635cdd1d5ac781c8142f9ada423c0700139403de..87c13f7be4ed5f65a866ae9ce473f5f1909afc94 100644
--- a/discovery/seata-discovery-zk/pom.xml
+++ b/discovery/seata-discovery-zk/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -34,18 +34,10 @@
         <dependency>
             <groupId>com.101tec</groupId>
             <artifactId>zkclient</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>slf4j-log4j12</artifactId>
-                    <groupId>org.slf4j</groupId>
-                </exclusion>
-            </exclusions>
         </dependency>
-
         <dependency>
             <groupId>org.apache.curator</groupId>
             <artifactId>curator-test</artifactId>
-            <version>2.9.1</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java b/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java
index 3788e0cfe92af4293f0a3f2e1da18cd8b3b87f3a..a78d5c31ba89aa3f06fe62404e878b172fb47d27 100644
--- a/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java
+++ b/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java
@@ -19,10 +19,10 @@ import io.seata.common.util.NetUtil;
 import org.I0Itec.zkclient.IZkChildListener;
 import org.I0Itec.zkclient.ZkClient;
 import org.apache.curator.test.TestingServer;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
 
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
@@ -35,41 +35,42 @@ import java.util.concurrent.TimeUnit;
  */
 public class ZookeeperRegisterServiceImplTest {
     protected static TestingServer server = null;
-    @BeforeClass
+
+    @BeforeAll
     public static void adBeforeClass() throws Exception {
         server = new TestingServer(2181, true);
         server.start();
     }
 
-    @AfterClass
+    @AfterAll
     public static void adAfterClass() throws Exception {
         if (server != null) {
             server.stop();
         }
     }
 
-    ZookeeperRegisterServiceImpl service  = (ZookeeperRegisterServiceImpl) new ZookeeperRegistryProvider().provide();
-    
+    ZookeeperRegisterServiceImpl service = (ZookeeperRegisterServiceImpl) new ZookeeperRegistryProvider().provide();
+
     @Test
     public void getInstance() {
         ZookeeperRegisterServiceImpl service1 = ZookeeperRegisterServiceImpl.getInstance();
-        Assert.assertEquals(service1, service);
+        Assertions.assertEquals(service1, service);
     }
-    
+
     @Test
     public void buildZkTest() {
         ZkClient client = service.buildZkClient("127.0.0.1:2181", 5000, 5000);
-        Assert.assertTrue(client.exists("/zookeeper"));
+        Assertions.assertTrue(client.exists("/zookeeper"));
     }
 
     @Test
     public void testAll() throws Exception {
         service.register(new InetSocketAddress(NetUtil.getLocalAddress(), 33333));
 
-        Assert.assertNull(service.lookup("xxx"));
+        Assertions.assertNull(service.lookup("xxx"));
         List<InetSocketAddress> lookup2 = service.doLookup("default");
-        Assert.assertTrue(lookup2.size() == 1);
-        
+        Assertions.assertTrue(lookup2.size() == 1);
+
         final List<String> data = new ArrayList<>();
         final CountDownLatch latch = new CountDownLatch(1);
         IZkChildListener listener = (s, list) -> {
@@ -86,13 +87,13 @@ public class ZookeeperRegisterServiceImplTest {
             latch2.countDown();
         };
         service.subscribe("default", listener2);
-        
+
         service.unregister(new InetSocketAddress(NetUtil.getLocalAddress(), 33333));
         latch2.await(1000, TimeUnit.MILLISECONDS);
-        Assert.assertTrue(data2.size() == 0);
-        
+        Assertions.assertTrue(data2.size() == 0);
+
         service.unsubscribe("default", listener);
         service.unsubscribe("default", listener2);
     }
 
-}
\ No newline at end of file
+}
diff --git a/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegistryProviderTest.java b/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegistryProviderTest.java
index 6cf299cfd10514aaa6c69436238c64997867162c..9cd0b817bf2af91a3dc0ec077a027ecb84d1f980 100644
--- a/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegistryProviderTest.java
+++ b/discovery/seata-discovery-zk/src/test/java/io/seata/discovery/registry/zk/ZookeeperRegistryProviderTest.java
@@ -15,8 +15,8 @@
  */
 package io.seata.discovery.registry.zk;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author Geng Zhang
@@ -26,7 +26,7 @@ public class ZookeeperRegistryProviderTest {
     @Test
     public void provide() {
         ZookeeperRegistryProvider provider = new ZookeeperRegistryProvider();
-        Assert.assertTrue(provider.provide() instanceof ZookeeperRegisterServiceImpl);
+        Assertions.assertTrue(provider.provide() instanceof ZookeeperRegisterServiceImpl);
     }
 
-}
\ No newline at end of file
+}
diff --git a/distribution/pom.xml b/distribution/pom.xml
index ca1f67844152f3df383ce3355bdbc54b2945eefb..fca8dafc10fa840b71af1dd37fc1655484d5850a 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
         <dependency>
             <groupId>io.seata</groupId>
             <artifactId>seata-server</artifactId>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
     <profiles>
@@ -40,6 +41,7 @@
                 <dependency>
                     <groupId>io.seata</groupId>
                     <artifactId>seata-server</artifactId>
+                    <version>${project.version}</version>
                 </dependency>
             </dependencies>
             <build>
diff --git a/distribution/release-seata.xml b/distribution/release-seata.xml
index 2346c93a70590991bd3c22f8841aaf50e1d06f3d..f79d01621d3a17e35663dbf14cabeb59688574dd 100644
--- a/distribution/release-seata.xml
+++ b/distribution/release-seata.xml
@@ -1,5 +1,5 @@
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -42,20 +42,18 @@
             </includes>
             <fileMode>0755</fileMode>
         </fileSet>
+
+        <fileSet>
+            <includes>
+                <include>lib/*</include>
+            </includes>
+        </fileSet>
     </fileSets>
     <files>
         <file>
             <source>LICENSE-BIN</source>
             <destName>LICENSE</destName>
         </file>
-        <file>
-            <source>NOTICE-BIN</source>
-            <destName>NOTICE</destName>
-        </file>
-        <file>
-            <source>../server/target/seata-server-${project.version}.jar</source>
-            <outputDirectory>/target/</outputDirectory>
-        </file>
     </files>
 
     <moduleSets>
diff --git a/integration/dubbo-alibaba/pom.xml b/integration/dubbo-alibaba/pom.xml
index fd8959c0b3b55151649d6a25d23df3a990b3b3a8..d5a45a15212e27c7422790bd13951a09d05dfa6f 100644
--- a/integration/dubbo-alibaba/pom.xml
+++ b/integration/dubbo-alibaba/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -33,11 +33,11 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-tm</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>dubbo</artifactId>
-            <version>2.6.5</version>
         </dependency>
     </dependencies>
 </project>
diff --git a/integration/dubbo/pom.xml b/integration/dubbo/pom.xml
index 85e3d81e99b4f63a697e125e37961b1a1237bb7c..e07efc2ff69713b99a7ac05aea9707bf71fe00d9 100644
--- a/integration/dubbo/pom.xml
+++ b/integration/dubbo/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-tm</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
diff --git a/integration/sofa-rpc/pom.xml b/integration/sofa-rpc/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cb01cca52af4cf4026c388974f3a784e9984adf8
--- /dev/null
+++ b/integration/sofa-rpc/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  Copyright 1999-2019 Seata.io Group.
+  ~
+  ~  Licensed 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">
+    <parent>
+        <groupId>io.seata</groupId>
+        <artifactId>seata-parent</artifactId>
+        <version>${revision}</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>seata-sofa-rpc</artifactId>
+    <packaging>jar</packaging>
+    <name>seata-sofa-rpc ${project.version}</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>seata-tm</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alipay.sofa</groupId>
+            <artifactId>sofa-rpc-all</artifactId>
+        </dependency>
+        
+    </dependencies>
+
+</project>
diff --git a/integration/sofa-rpc/src/main/java/io/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java b/integration/sofa-rpc/src/main/java/io/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..678dfecddc99e1eeca8af8c612e4d97263796623
--- /dev/null
+++ b/integration/sofa-rpc/src/main/java/io/seata/integration/sofa/rpc/TransactionContextConsumerFilter.java
@@ -0,0 +1,86 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.integration.sofa.rpc;
+
+import com.alipay.sofa.rpc.context.RpcInternalContext;
+import com.alipay.sofa.rpc.core.exception.SofaRpcException;
+import com.alipay.sofa.rpc.core.request.SofaRequest;
+import com.alipay.sofa.rpc.core.response.SofaResponse;
+import com.alipay.sofa.rpc.ext.Extension;
+import com.alipay.sofa.rpc.filter.AutoActive;
+import com.alipay.sofa.rpc.filter.Filter;
+import com.alipay.sofa.rpc.filter.FilterInvoker;
+import io.seata.core.context.RootContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TransactionContext on consumer side.
+ * 
+ * @author Geng Zhang
+ * @since 0.6.0
+ */
+@Extension(value = "transactionContextConsumer")
+@AutoActive(consumerSide = true)
+public class TransactionContextConsumerFilter extends Filter {
+
+    /**
+     * Logger for this class
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(TransactionContextConsumerFilter.class);
+
+    @Override
+    public SofaResponse invoke(FilterInvoker filterInvoker, SofaRequest sofaRequest) throws SofaRpcException {
+        String xid = RootContext.getXID();
+        String rpcXid = (String) RpcInternalContext.getContext().getAttachment(RootContext.KEY_XID);
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("xid in RootContext[" + xid + "] xid in RpcContext[" + rpcXid + "]");
+        }
+        boolean bind = false;
+        if (xid != null) {
+            sofaRequest.addRequestProp(RootContext.KEY_XID, xid);
+        } else {
+            if (rpcXid != null) {
+                RootContext.bind(rpcXid);
+                bind = true;
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("bind[" + rpcXid + "] to RootContext");
+                }
+            }
+        }
+        try {
+            return filterInvoker.invoke(sofaRequest);
+        } finally {
+            if (bind) {
+                String unbindXid = RootContext.unbind();
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("unbind[" + unbindXid + "] from RootContext");
+                }
+                if (!rpcXid.equalsIgnoreCase(unbindXid)) {
+                    if (LOGGER.isWarnEnabled()) {
+                        LOGGER.warn("xid in change during RPC from " + rpcXid + " to " + unbindXid);
+                    }
+                    if (unbindXid != null) {
+                        RootContext.bind(unbindXid);
+                        if (LOGGER.isWarnEnabled()) {
+                            LOGGER.warn("bind [" + unbindXid + "] back to RootContext");
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/integration/sofa-rpc/src/main/java/io/seata/integration/sofa/rpc/TransactionContextProviderFilter.java b/integration/sofa-rpc/src/main/java/io/seata/integration/sofa/rpc/TransactionContextProviderFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..02a9b36bc2e4af9ca1946b3209e0acbaf8b41702
--- /dev/null
+++ b/integration/sofa-rpc/src/main/java/io/seata/integration/sofa/rpc/TransactionContextProviderFilter.java
@@ -0,0 +1,86 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.integration.sofa.rpc;
+
+import com.alipay.sofa.rpc.context.RpcInternalContext;
+import com.alipay.sofa.rpc.core.exception.SofaRpcException;
+import com.alipay.sofa.rpc.core.request.SofaRequest;
+import com.alipay.sofa.rpc.core.response.SofaResponse;
+import com.alipay.sofa.rpc.ext.Extension;
+import com.alipay.sofa.rpc.filter.AutoActive;
+import com.alipay.sofa.rpc.filter.Filter;
+import com.alipay.sofa.rpc.filter.FilterInvoker;
+import io.seata.core.context.RootContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TransactionContext on provider side.
+ * 
+ * @author Geng Zhang
+ * @since 0.6.0
+ */
+@Extension(value = "transactionContextProvider")
+@AutoActive(providerSide = true)
+public class TransactionContextProviderFilter extends Filter {
+
+    /**
+     * Logger for this class
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(TransactionContextProviderFilter.class);
+
+    @Override
+    public SofaResponse invoke(FilterInvoker filterInvoker, SofaRequest sofaRequest) throws SofaRpcException {
+        String xid = RootContext.getXID();
+        String rpcXid = (String) sofaRequest.getRequestProp(RootContext.KEY_XID);
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("xid in RootContext[" + xid + "] xid in RpcContext[" + rpcXid + "]");
+        }
+        boolean bind = false;
+        if (xid != null) {
+            RpcInternalContext.getContext().setAttachment(RootContext.KEY_XID, xid);
+        } else {
+            if (rpcXid != null) {
+                RootContext.bind(rpcXid);
+                bind = true;
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("bind[" + rpcXid + "] to RootContext");
+                }
+            }
+        }
+        try {
+            return filterInvoker.invoke(sofaRequest);
+        } finally {
+            if (bind) {
+                String unbindXid = RootContext.unbind();
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("unbind[" + unbindXid + "] from RootContext");
+                }
+                if (!rpcXid.equalsIgnoreCase(unbindXid)) {
+                    if (LOGGER.isWarnEnabled()) {
+                        LOGGER.warn("xid in change during RPC from " + rpcXid + " to " + unbindXid);
+                    }
+                    if (unbindXid != null) {
+                        RootContext.bind(unbindXid);
+                        if (LOGGER.isWarnEnabled()) {
+                            LOGGER.warn("bind [" + unbindXid + "] back to RootContext");
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/integration/sofa-rpc/src/main/resources/META-INF/services/com.alipay.sofa.rpc.filter.Filter b/integration/sofa-rpc/src/main/resources/META-INF/services/com.alipay.sofa.rpc.filter.Filter
new file mode 100644
index 0000000000000000000000000000000000000000..4bbbb3392b89d8e2a251cccb8346eb89cb9d4f96
--- /dev/null
+++ b/integration/sofa-rpc/src/main/resources/META-INF/services/com.alipay.sofa.rpc.filter.Filter
@@ -0,0 +1,2 @@
+io.seata.integration.sofa.rpc.TransactionContextProviderFilter
+io.seata.integration.sofa.rpc.TransactionContextConsumerFilter
\ No newline at end of file
diff --git a/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloService.java b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloService.java
new file mode 100644
index 0000000000000000000000000000000000000000..18d58a57529172423b640810214b26b0c8f81ba1
--- /dev/null
+++ b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloService.java
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.integration.sofa.rpc;
+
+/**
+ * @author Geng Zhang
+ */
+public interface HelloService {
+
+    String sayHello(String name, int age);
+}
diff --git a/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloServiceImpl.java b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..38dc798fd743ad7963f3d530b257a3bbae357d35
--- /dev/null
+++ b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloServiceImpl.java
@@ -0,0 +1,46 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.integration.sofa.rpc;
+
+import io.seata.core.context.RootContext;
+
+/**
+ * @author Geng Zhang
+ */
+public class HelloServiceImpl implements HelloService {
+
+    private String result;
+    
+    private String xid;
+
+    public HelloServiceImpl() {
+
+    }
+
+    public HelloServiceImpl(String result) {
+        this.result = result;
+    }
+
+    @Override
+    public String sayHello(String name, int age) {
+        xid = RootContext.getXID();
+        return result != null ? result : "hello " + name + " from server! age: " + age;
+    }
+
+    public String getXid() {
+        return xid;
+    }
+}
diff --git a/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloServiceProxy.java b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloServiceProxy.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e593e73efcd994da568720b45cb71796af9e92c
--- /dev/null
+++ b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/HelloServiceProxy.java
@@ -0,0 +1,42 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.integration.sofa.rpc;
+
+import io.seata.core.context.RootContext;
+
+/**
+ * @author Geng Zhang
+ */
+public class HelloServiceProxy implements HelloService {
+
+    private String xid;
+
+    private HelloService proxy;
+
+    public HelloServiceProxy(HelloService proxy) {
+        this.proxy = proxy;
+    }
+
+    @Override
+    public String sayHello(String name, int age) {
+        xid = RootContext.getXID();
+        return proxy.sayHello(name, age);
+    }
+
+    public String getXid() {
+        return xid;
+    }
+}
diff --git a/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/TransactionContextFilterTest.java b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/TransactionContextFilterTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7060e0c92fdb41045c22c680e4b66a106c484fd3
--- /dev/null
+++ b/integration/sofa-rpc/src/test/java/io/seata/integration/sofa/rpc/TransactionContextFilterTest.java
@@ -0,0 +1,127 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.integration.sofa.rpc;
+
+import com.alipay.sofa.rpc.config.ConsumerConfig;
+import com.alipay.sofa.rpc.config.ProviderConfig;
+import com.alipay.sofa.rpc.config.ServerConfig;
+import com.alipay.sofa.rpc.context.RpcInternalContext;
+import com.alipay.sofa.rpc.context.RpcInvokeContext;
+import com.alipay.sofa.rpc.context.RpcRunningState;
+import com.alipay.sofa.rpc.context.RpcRuntimeContext;
+import com.alipay.sofa.rpc.core.exception.SofaRpcException;
+import io.seata.core.context.RootContext;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author Geng Zhang
+ */
+public class TransactionContextFilterTest {
+
+    @Test
+    public void testAll() {
+        HelloServiceImpl helloServiceImpl;
+        HelloService helloServiceRef;
+        HelloServiceProxy helloServiceProxy;
+        HelloService helloService;
+
+        // mock A -> B -> C
+
+        { // C
+            ServerConfig serverConfig1 = new ServerConfig()
+                    .setStopTimeout(0).setPort(22222)
+                    .setQueues(5).setCoreThreads(1).setMaxThreads(1);
+            helloServiceImpl = new HelloServiceImpl();
+            ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>()
+                    .setInterfaceId(HelloService.class.getName())
+                    .setRef(helloServiceImpl)
+                    .setServer(serverConfig1)
+                    .setUniqueId("x1")
+                    .setRegister(false);
+            providerConfig.export();
+        }
+        { // B
+            ConsumerConfig<HelloService> consumerConfig = new ConsumerConfig<HelloService>()
+                    .setInterfaceId(HelloService.class.getName())
+                    .setTimeout(1000)
+                    .setDirectUrl("bolt://127.0.0.1:22222")
+                    .setUniqueId("x1")
+                    .setRegister(false);
+            helloServiceRef = consumerConfig.refer();
+
+            ServerConfig serverConfig2 = new ServerConfig()
+                    .setStopTimeout(0).setPort(22223)
+                    .setQueues(5).setCoreThreads(1).setMaxThreads(1);
+            helloServiceProxy = new HelloServiceProxy(helloServiceRef);
+            ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>()
+                    .setInterfaceId(HelloService.class.getName())
+                    .setRef(helloServiceProxy)
+                    .setServer(serverConfig2)
+                    .setUniqueId("x2")
+                    .setRegister(false);
+            providerConfig.export();
+        }
+        { // A
+            ConsumerConfig<HelloService> consumerConfig = new ConsumerConfig<HelloService>()
+                    .setInterfaceId(HelloService.class.getName())
+                    .setTimeout(1000)
+                    .setDirectUrl("bolt://127.0.0.1:22223")
+                    .setUniqueId("x2")
+                    .setRegister(false);
+            helloService = consumerConfig.refer();
+        }
+
+        try {
+            helloService.sayHello("xxx", 22);
+            // check C
+            Assertions.assertNull(helloServiceImpl.getXid());
+            // check B
+            Assertions.assertNull(helloServiceProxy.getXid());
+        } catch (Exception e) {
+            Assertions.assertTrue(e instanceof SofaRpcException);
+        } finally {
+            Assertions.assertNull(RootContext.unbind());
+        }
+
+        RootContext.bind("xidddd");
+        try {
+            helloService.sayHello("xxx", 22);
+            // check C
+            Assertions.assertEquals(helloServiceImpl.getXid(), "xidddd");
+            // check B
+            Assertions.assertEquals(helloServiceProxy.getXid(), "xidddd");
+        } catch (Exception e) {
+            Assertions.assertTrue(e instanceof SofaRpcException);
+        } finally {
+            Assertions.assertEquals("xidddd", RootContext.unbind());
+        }
+    }
+
+    @BeforeAll
+    public static void adBeforeClass() {
+        RpcRunningState.setUnitTestMode(true);
+    }
+
+    @AfterAll
+    public static void adAfterClass() {
+        RpcRuntimeContext.destroy();
+        RpcInternalContext.removeContext();
+        RpcInvokeContext.removeContext();
+    }
+}
\ No newline at end of file
diff --git a/mvnw b/mvnw
index af3a05b7b073b8e889adcfb44e6bfc6d2fb66336..bbd6c05075056736941b23fc4802e0960161243b 100755
--- a/mvnw
+++ b/mvnw
@@ -1,6 +1,6 @@
 #!/bin/sh
 # ----------------------------------------------------------------------------
-# Copyright 1999-2018 Alibaba Group Holding Ltd.
+# Copyright 1999-2019 Seata.io Group.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/mvnw.cmd b/mvnw.cmd
index 0bca9dc672162aee8868bcc2a9ec3b33d3a777f0..0dd17319b8f1ad7f85cdea821339a2d6319cc09c 100755
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -1,5 +1,5 @@
 @REM ----------------------------------------------------------------------------
-@REM Copyright 1999-2018 Alibaba Group Holding Ltd.
+@REM Copyright 1999-2019 Seata.io Group.
 @REM
 @REM Licensed under the Apache License, Version 2.0 (the "License");
 @REM you may not use this file except in compliance with the License.
diff --git a/pom.xml b/pom.xml
index d40c2248302c3ad1605f0801b349858f5840a1eb..e3628dda5353c2e1ae04bd8d33249e61d80f6352 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
     <artifactId>seata-parent</artifactId>
     <version>${revision}</version>
     <modules>
+        <module>all</module>
+        <module>bom</module>
         <module>common</module>
         <module>config</module>
         <module>core</module>
@@ -30,6 +32,7 @@
         <module>distribution</module>
         <module>integration/dubbo</module>
         <module>integration/dubbo-alibaba</module>
+        <module>integration/sofa-rpc</module>
         <module>rm</module>
         <module>rm-datasource</module>
         <module>server</module>
@@ -44,7 +47,7 @@
     <url>http://seata.io</url>
     <description>top seata project pom.xml file</description>
     <prerequisites>
-        <maven>3.2.5</maven>
+        <maven>3.6.0</maven>
     </prerequisites>
     <licenses>
         <license>
@@ -79,46 +82,18 @@
 
     <properties>
         <!-- seata version -->
-        <revision>0.5.1</revision>
+        <revision>0.5.2</revision>
 
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <!-- Maven properties -->
-        <maven.test.skip>false</maven.test.skip>
-        <!--<maven.javadoc.skip>true</maven.javadoc.skip>-->
         <!-- Compiler settings properties -->
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
-        <netty4.version>4.1.24.Final</netty4.version>
-        <org.springframework.spring.version>2.5.6.SEC03</org.springframework.spring.version>
-        <junit.version>4.12</junit.version>
-        <dubbo.version>2.7.0</dubbo.version>
-        <fastjson.version>1.2.48</fastjson.version>
-        <config.version>1.2.1</config.version>
-        <slf4j-api.version>1.7.22</slf4j-api.version>
-        <logback-classic.version>1.2.0</logback-classic.version>
-        <commons-lang.version>2.6</commons-lang.version>
-        <commons-pool2.version>2.4.2</commons-pool2.version>
-        <commons-pool.version>1.6</commons-pool.version>
-        <cglib.version>3.1</cglib.version>
-        <aopalliance.version>1.0</aopalliance.version>
-        <zkclient.version>0.10</zkclient.version>
-        <spring-context-support.version>1.0.2</spring-context-support.version>
-        <testng.version>6.4</testng.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <!-- Maven plugins -->
+        <maven.test.skip>false</maven.test.skip>
         <jacoco-maven-plugin.version>0.8.3</jacoco-maven-plugin.version>
-        <apollo-client.version>1.1.0</apollo-client.version>
-        <redis-clients.version>2.9.0</redis-clients.version>
-        <eureka-clients.version>1.9.5</eureka-clients.version>
-        <consul-clients.version>1.4.2</consul-clients.version>
-        <nacos-client.version>0.9.1</nacos-client.version>
-        <etcd-client-v3.version>0.3.0</etcd-client-v3.version>
-        <testcontainers.version>1.11.2</testcontainers.version>
-        <guava.version>27.0.1-jre</guava.version>
-        <javax-inject.version>1</javax-inject.version>
-        <archaius-core.version>0.7.6</archaius-core.version>
-        <sofa.registry.version>5.2.0</sofa.registry.version>
         <flatten-maven-plugin.version>1.1.0</flatten-maven-plugin.version>
+        <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
         <maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
         <p3c-pmd.version>1.3.6</p3c-pmd.version>
         <maven-pmd-plugin.version>3.8</maven-pmd-plugin.version>
@@ -126,296 +101,59 @@
         <maven-source-plugin.version>2.2.1</maven-source-plugin.version>
         <license-maven-plugin.version>3.0</license-maven-plugin.version>
         <maven-checkstyle-plugin.version>3.0.0</maven-checkstyle-plugin.version>
+
+        <!-- for test -->
+        <junit-jupiter.version>5.4.2</junit-jupiter.version>
+        <mockito-core.version>2.23.4</mockito-core.version>
+        <assertj-core.version>3.12.2</assertj-core.version>
+        <junit-platform-launcher.version>1.4.2</junit-platform-launcher.version>
     </properties>
+
     <!--test-->
     <dependencies>
         <dependency>
-            <groupId>org.assertj</groupId>
-            <artifactId>assertj-core</artifactId>
-            <version>2.6.0</version>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <version>${junit-platform-launcher.version}</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
-            <version>2.23.4</version>
+            <version>${mockito-core.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>${assertj-core.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-common</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-config</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-server</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-rm-datasource</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-tm</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-spring</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-dubbo</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-all</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-consul</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-eureka</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-zk</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-redis</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-sofa</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-nacos</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-discovery-etcd3</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-config-core</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-config-apollo</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-config-nacos</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-config-zk</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-config-all</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-tcc</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-rm</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${project.groupId}</groupId>
-                <artifactId>seata-test</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.netty</groupId>
-                <artifactId>netty-all</artifactId>
-                <version>${netty4.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.alibaba</groupId>
-                <artifactId>fastjson</artifactId>
-                <version>${fastjson.version}</version>
+                <groupId>io.seata</groupId>
+                <artifactId>seata-bom</artifactId>
+                <version>${revision}</version>
+                <type>pom</type>
+                <scope>import</scope>
             </dependency>
-            <dependency>
-                <groupId>org.springframework</groupId>
-                <artifactId>spring</artifactId>
-                <version>${org.springframework.spring.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.typesafe</groupId>
-                <artifactId>config</artifactId>
-                <version>${config.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-api</artifactId>
-                <version>${slf4j-api.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>ch.qos.logback</groupId>
-                <artifactId>logback-classic</artifactId>
-                <version>${logback-classic.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>commons-lang</groupId>
-                <artifactId>commons-lang</artifactId>
-                <version>${commons-lang.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.commons</groupId>
-                <artifactId>commons-pool2</artifactId>
-                <version>${commons-pool2.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>commons-pool</groupId>
-                <artifactId>commons-pool</artifactId>
-                <version>${commons-pool.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>junit</groupId>
-                <artifactId>junit</artifactId>
-                <version>${junit.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.testng</groupId>
-                <artifactId>testng</artifactId>
-                <version>${testng.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.dubbo</groupId>
-                <artifactId>dubbo</artifactId>
-                <version>${dubbo.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>cglib</groupId>
-                <artifactId>cglib</artifactId>
-                <version>${cglib.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>aopalliance</groupId>
-                <artifactId>aopalliance</artifactId>
-                <version>${aopalliance.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.101tec</groupId>
-                <artifactId>zkclient</artifactId>
-                <version>${zkclient.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.alipay.sofa</groupId>
-                <artifactId>registry-client-all</artifactId>
-                <version>${sofa.registry.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.alibaba.spring</groupId>
-                <artifactId>spring-context-support</artifactId>
-                <version>${spring-context-support.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.alibaba.nacos</groupId>
-                <artifactId>nacos-client</artifactId>
-                <version>${nacos-client.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.ctrip.framework.apollo</groupId>
-                <artifactId>apollo-client</artifactId>
-                <version>${apollo-client.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>redis.clients</groupId>
-                <artifactId>jedis</artifactId>
-                <version>${redis-clients.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.netflix.eureka</groupId>
-                <artifactId>eureka-client</artifactId>
-                <version>${eureka-clients.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.ecwid.consul</groupId>
-                <artifactId>consul-api</artifactId>
-                <version>${consul-clients.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.etcd</groupId>
-                <artifactId>jetcd-core</artifactId>
-                <version>${etcd-client-v3.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.etcd</groupId>
-                <artifactId>jetcd-launcher</artifactId>
-                <version>${etcd-client-v3.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.testcontainers</groupId>
-                <artifactId>testcontainers</artifactId>
-                <version>${testcontainers.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.google.guava</groupId>
-                <artifactId>guava</artifactId>
-                <version>${guava.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>javax.inject</groupId>
-                <artifactId>javax.inject</artifactId>
-                <version>${javax-inject.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.netflix.archaius</groupId>
-                <artifactId>archaius-core</artifactId>
-                <version>${archaius-core.version}</version>
-            </dependency>
-        </dependencies>
 
+        </dependencies>
     </dependencyManagement>
 
     <profiles>
@@ -423,20 +161,6 @@
             <id>release</id>
             <build>
                 <plugins>
-                    <!-- Source -->
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-source-plugin</artifactId>
-                        <version>${maven-source-plugin.version}</version>
-                        <executions>
-                            <execution>
-                                <phase>package</phase>
-                                <goals>
-                                    <goal>jar-no-fork</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
                     <!-- Javadoc -->
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
@@ -510,6 +234,20 @@
             </extension>
         </extensions>
         <plugins>
+            <!-- Source -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>${maven-source-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>jar-no-fork</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-pmd-plugin</artifactId>
@@ -575,6 +313,11 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${maven-surefire-plugin.version}</version>
+            </plugin>
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>flatten-maven-plugin</artifactId>
diff --git a/rm-datasource/pom.xml b/rm-datasource/pom.xml
index 86d3665e9a212d8c89718ced74200b39a0818f4b..8ab21440bb40ac1e7b263efc4cf52e62eadbf24c 100644
--- a/rm-datasource/pom.xml
+++ b/rm-datasource/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -32,27 +32,22 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-core</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-rm</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>druid</artifactId>
-            <version>1.1.12</version>
         </dependency>
         <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <version>18.0</version>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>${junit.version}</version>
-            <scope>test</scope>
+            <groupId>com.github.ben-manes.caffeine</groupId>
+            <artifactId>caffeine</artifactId>
         </dependency>
+
     </dependencies>
 
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java
index f1400f49aa0648025fa2b37d12ebc7ab644d7ff8..f6076f882042d4e9c68a8e314bd3295da489e18a 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/AsyncWorker.java
@@ -26,8 +26,6 @@ import io.seata.core.model.BranchType;
 import io.seata.core.model.ResourceManagerInbound;
 import io.seata.rm.DefaultResourceManager;
 import io.seata.rm.datasource.undo.UndoLogManager;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,11 +33,12 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionContext.java b/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionContext.java
index 06addce1b0eacd9c95a569ce11215b9ac9d5fbad..5eb96a49ada14749c39e18a54bcfe8e5b4ee004b 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionContext.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionContext.java
@@ -16,12 +16,13 @@
 package io.seata.rm.datasource;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.rm.datasource.undo.SQLUndoLog;
-import io.seata.rm.datasource.undo.SQLUndoLog;
 
 /**
  * The type Connection context.
@@ -32,7 +33,8 @@ public class ConnectionContext {
     private String xid;
     private Long branchId;
     private boolean isGlobalLockRequire;
-    private List<String> lockKeysBuffer = new ArrayList<>();
+    //table and primary key should not be duplicated
+    private Set<String> lockKeysBuffer = new HashSet<>();
     private List<SQLUndoLog> sqlUndoItemsBuffer = new ArrayList<>();
 
     /**
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java
index 3ebfdb86388c99353de6ef04eb507544fc9231b4..ed59c4016a0dcd4bedfbf3fb0a409a45f8910ae5 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/ConnectionProxy.java
@@ -25,9 +25,6 @@ import io.seata.rm.DefaultResourceManager;
 import io.seata.rm.datasource.exec.LockConflictException;
 import io.seata.rm.datasource.undo.SQLUndoLog;
 import io.seata.rm.datasource.undo.UndoLogManager;
-import io.seata.rm.datasource.exec.LockConflictException;
-import io.seata.rm.datasource.undo.SQLUndoLog;
-import io.seata.rm.datasource.undo.UndoLogManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..c707830f7943cb54811932313191cd67290985db
--- /dev/null
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataCompareUtils.java
@@ -0,0 +1,150 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.rm.datasource;
+
+import io.seata.common.util.CollectionUtils;
+import io.seata.common.util.StringUtils;
+import io.seata.rm.datasource.sql.struct.Field;
+import io.seata.rm.datasource.sql.struct.Row;
+import io.seata.rm.datasource.sql.struct.TableMeta;
+import io.seata.rm.datasource.sql.struct.TableRecords;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The type Data compare utils.
+ *
+ * @author Geng Zhang
+ */
+public class DataCompareUtils {
+
+    /**
+     * Is field equals.
+     *
+     * @param f0 the f0
+     * @param f1  the f1
+     * @return the boolean
+     */
+    public static boolean isFieldEquals(Field f0, Field f1) {
+        if (f0 == null) {
+            return f1 == null;
+        } else {
+            if (f1 == null) {
+                return false;
+            } else {
+                if (StringUtils.equalsIgnoreCase(f0.getName(), f1.getName())
+                        && f0.getType() == f1.getType()) {
+                    if (f0.getValue() == null) {
+                        return f1.getValue() == null;
+                    } else {
+                        if (f1.getValue() == null) {
+                            return false;
+                        } else {
+                            return f0.getValue().equals(f1.getValue());
+                        }
+                    }
+                } else {
+                    return false;
+                }
+            }
+        }
+    }
+
+    /**
+     * Is image equals.
+     *
+     * @param beforeImage the before image
+     * @param afterImage  the after image
+     * @return boolean
+     */
+    public static boolean isRecordsEquals(TableRecords beforeImage, TableRecords afterImage) {
+        if (beforeImage == null) {
+            return afterImage == null;
+        } else {
+            if (afterImage == null) {
+                return false;
+            } else {
+                if (beforeImage.getTableName().equalsIgnoreCase(afterImage.getTableName())
+                        && CollectionUtils.isSizeEquals(beforeImage.getRows(), afterImage.getRows())) {
+                    return compareRows(beforeImage.getTableMeta(), beforeImage.getRows(), afterImage.getRows());
+                } else {
+                    return false;
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Is rows equals.
+     *
+     * @param tableMetaData the table meta data
+     * @param oldRows       the old rows
+     * @param newRows       the new rows
+     * @return the boolean
+     */
+    public static boolean isRowsEquals(TableMeta tableMetaData, List<Row> oldRows, List<Row> newRows) {
+        return CollectionUtils.isSizeEquals(oldRows, newRows) && compareRows(tableMetaData, oldRows, newRows);
+    }
+
+    private static boolean compareRows(TableMeta tableMetaData, List<Row> oldRows, List<Row> newRows) {
+        // old row to map
+        Map<String, Map<String, Field>> oldRowsMap = rowListToMap(oldRows, tableMetaData.getPkName());
+        // new row to map
+        Map<String, Map<String, Field>> newRowsMap = rowListToMap(newRows, tableMetaData.getPkName());
+        // compare data
+        for (String rowKey : oldRowsMap.keySet()) {
+            Map<String, Field> oldRow = oldRowsMap.get(rowKey);
+            Map<String, Field> newRow = newRowsMap.get(rowKey);
+            if (newRow == null) {
+                return false;
+            }
+            for (String fieldName : oldRow.keySet()) {
+                Field oldField = oldRow.get(fieldName);
+                Field newField = newRow.get(fieldName);
+                if (newField == null) {
+                    return false;
+                }
+                if (!isFieldEquals(oldField, newField)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, Map<String, Field>> rowListToMap(List<Row> rowList, String primaryKey) {
+        // {value of primaryKey, value of all columns}
+        Map<String, Map<String, Field>> rowMap = new HashMap<>();
+        for (Row row : rowList) {
+            // {uppercase fieldName : field}
+            Map<String, Field> colsMap = new HashMap<>();
+            String rowKey = null;
+            for (int j = 0; j < row.getFields().size(); j++) {
+                Field field = row.getFields().get(j);
+                if (field.getName().equalsIgnoreCase(primaryKey)) {
+                    rowKey = String.valueOf(field.getValue());
+                }
+                colsMap.put(field.getName().trim().toUpperCase(), field);
+            }
+            rowMap.put(rowKey, colsMap);
+        }
+        return rowMap;
+    }
+
+}
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java
index 0c17a1b272f4a2b92859d2a96fe1da1ff1ccb0d8..b1ad1b7e9b62dd1b261b43efca4154a0ec329198 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceManager.java
@@ -15,12 +15,6 @@
  */
 package io.seata.rm.datasource;
 
-import java.net.InetSocketAddress;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeoutException;
-
 import io.seata.common.exception.FrameworkException;
 import io.seata.common.exception.NotSupportYetException;
 import io.seata.common.exception.ShouldNeverHappenException;
@@ -42,12 +36,16 @@ import io.seata.core.rpc.netty.TmRpcClient;
 import io.seata.discovery.loadbalance.LoadBalanceFactory;
 import io.seata.discovery.registry.RegistryFactory;
 import io.seata.rm.AbstractResourceManager;
-import io.seata.rm.datasource.undo.UndoLogManager;
-
 import io.seata.rm.datasource.undo.UndoLogManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeoutException;
+
 import static io.seata.common.exception.FrameworkErrorCode.NoAvailableService;
 
 /**
@@ -74,7 +72,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia
 
     @Override
     public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
-        throws TransactionException {
+            throws TransactionException {
         try {
             GlobalLockQueryRequest request = new GlobalLockQueryRequest();
             request.setXid(xid);
@@ -83,17 +81,17 @@ public class DataSourceManager extends AbstractResourceManager implements Initia
 
             GlobalLockQueryResponse response = null;
             if (RootContext.inGlobalTransaction()) {
-                response = (GlobalLockQueryResponse)RmRpcClient.getInstance().sendMsgWithResponse(request);
+                response = (GlobalLockQueryResponse) RmRpcClient.getInstance().sendMsgWithResponse(request);
             } else if (RootContext.requireGlobalLock()) {
-                response = (GlobalLockQueryResponse)RmRpcClient.getInstance().sendMsgWithResponse(loadBalance(),
-                    request, NettyClientConfig.getRpcRequestTimeout());
+                response = (GlobalLockQueryResponse) RmRpcClient.getInstance().sendMsgWithResponse(loadBalance(),
+                        request, NettyClientConfig.getRpcRequestTimeout());
             } else {
                 throw new RuntimeException("unknow situation!");
             }
 
             if (response.getResultCode() == ResultCode.Failed) {
                 throw new TransactionException(response.getTransactionExceptionCode(),
-                    "Response[" + response.getMsg() + "]");
+                        "Response[" + response.getMsg() + "]");
             }
             return response.isLockable();
         } catch (TimeoutException toe) {
@@ -109,7 +107,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia
         InetSocketAddress address = null;
         try {
             List<InetSocketAddress> inetSocketAddressList = RegistryFactory.getInstance().lookup(
-                TmRpcClient.getInstance().getTransactionServiceGroup());
+                    TmRpcClient.getInstance().getTransactionServiceGroup());
             address = LoadBalanceFactory.getInstance().select(inetSocketAddressList);
         } catch (Exception ignore) {
             LOGGER.error(ignore.getMessage());
@@ -136,7 +134,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia
     }
 
     @Override
-    public void init(){
+    public void init() {
         AsyncWorker asyncWorker = new AsyncWorker();
         asyncWorker.init();
         initAsyncWorker(asyncWorker);
@@ -161,7 +159,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia
      * @return the data source proxy
      */
     public DataSourceProxy get(String resourceId) {
-        return (DataSourceProxy)dataSourceCache.get(resourceId);
+        return (DataSourceProxy) dataSourceCache.get(resourceId);
     }
 
     @Override
@@ -194,7 +192,7 @@ public class DataSourceManager extends AbstractResourceManager implements Initia
     }
 
     @Override
-    public BranchType getBranchType(){
+    public BranchType getBranchType() {
         return BranchType.AT;
     }
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java
index 79f534dab655e1c2784f164d7873a14b2b12d3a1..32ffbe98547b4036748ea79212b6435f6c4f92de 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/DataSourceProxy.java
@@ -15,15 +15,17 @@
  */
 package io.seata.rm.datasource;
 
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
 import com.alibaba.druid.util.JdbcUtils;
+
 import io.seata.core.model.BranchType;
 import io.seata.core.model.Resource;
 import io.seata.rm.DefaultResourceManager;
 
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.SQLException;
-
 /**
  * The type Data source proxy.
  *
@@ -65,7 +67,7 @@ public class DataSourceProxy extends AbstractDataSourceProxy implements Resource
             jdbcUrl = connection.getMetaData().getURL();
             dbType = JdbcUtils.getDbType(jdbcUrl, null);
         } catch (SQLException e) {
-            throw new IllegalStateException(String.format("can not init dataSource :%s", e.getSQLState()));
+            throw new IllegalStateException("can not init dataSource", e);
         }
         DefaultResourceManager.get().registerResource(this);
     }
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLType.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLType.java
index 4fdb9d35c9d993e553d77f6bcbfa91be8665e099..8ed03711414376ac07b8135e90b7afbb8e236bf2 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLType.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/SQLType.java
@@ -91,7 +91,7 @@ public enum SQLType {
      */
     EXPLAIN(16),
     /**
-     * 存储过程
+     * Stored procedure
      */
     PROCEDURE(17),
     /**
@@ -99,7 +99,7 @@ public enum SQLType {
      */
     DESC(18),
     /**
-     * 获取上一个insert id
+     * Select last insert id
      */
     SELECT_LAST_INSERT_ID(19),
     /**
@@ -200,7 +200,7 @@ public enum SQLType {
     CHECK_TABLE(43),
 
     /**
-     * 获取上sql_calc_found_rows 的结果
+     * Select found rows.
      */
     SELECT_FOUND_ROWS(44),
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizer.java
index 801e568375081539a003916af71017e0234373fc..b82ad85067d14d2ef644ca5f4564e87fb4ea4874 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizer.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizer.java
@@ -19,7 +19,9 @@ import java.util.ArrayList;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
 import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
+import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
 import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
 import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
 import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
@@ -91,7 +93,15 @@ public class MySQLDeleteRecognizer extends BaseRecognizer implements SQLDeleteRe
                 return super.visit(x);
             }
         };
-        visitor.visit((SQLBinaryOpExpr)where);
+        if (where instanceof SQLBinaryOpExpr) {
+            visitor.visit((SQLBinaryOpExpr)where);
+        } else if (where instanceof SQLInListExpr) {
+            visitor.visit((SQLInListExpr) where);
+        } else if (where instanceof SQLBetweenExpr) {
+            visitor.visit((SQLBetweenExpr) where);
+        } else {
+            throw new IllegalArgumentException("unexpected WHERE expr: " + where.getClass().getSimpleName());
+        }
         return sb.toString();
     }
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizer.java
index 2adff88564fd98e71eb78821115e503a43b504b1..31fbaa09d652b18b39e9097ffb26522a56d4ee6c 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizer.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizer.java
@@ -19,7 +19,9 @@ import java.util.ArrayList;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
 import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
+import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
 import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
 import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
 import com.alibaba.druid.sql.ast.statement.SQLSelect;
@@ -76,7 +78,15 @@ public class MySQLSelectForUpdateRecognizer extends BaseRecognizer implements SQ
                 return super.visit(x);
             }
         };
-        visitor.visit((SQLBinaryOpExpr)where);
+        if (where instanceof SQLBinaryOpExpr) {
+            visitor.visit((SQLBinaryOpExpr)where);
+        } else if (where instanceof SQLInListExpr) {
+            visitor.visit((SQLInListExpr) where);
+        } else if (where instanceof SQLBetweenExpr) {
+            visitor.visit((SQLBetweenExpr) where);
+        } else {
+            throw new IllegalArgumentException("unexpected WHERE expr: " + where.getClass().getSimpleName());
+        }
         return sb.toString();
     }
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizer.java
index 6d3a8c34ea9a58a32490e6cbdf2f117c83db2f3a..e6f1aec129e541ea59b9b6ffd217517f8fc64589 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizer.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizer.java
@@ -117,7 +117,15 @@ public class MySQLUpdateRecognizer extends BaseRecognizer implements SQLUpdateRe
                 return super.visit(x);
             }
         };
-        visitor.visit((SQLBinaryOpExpr)where);
+        if (where instanceof SQLBinaryOpExpr) {
+            visitor.visit((SQLBinaryOpExpr)where);
+        } else if (where instanceof SQLInListExpr) {
+            visitor.visit((SQLInListExpr) where);
+        } else if (where instanceof SQLBetweenExpr) {
+            visitor.visit((SQLBetweenExpr) where);
+        } else {
+            throw new IllegalArgumentException("unexpected WHERE expr: " + where.getClass().getSimpleName());
+        }
         return sb.toString();
     }
 
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Field.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Field.java
index fa798d215f4395153011b13d846dfe07c2e14517..8094b6d7463affea83e95c07e70e61123a66d065 100755
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Field.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Field.java
@@ -25,19 +25,19 @@ public class Field {
     /**
      * The Name.
      */
-    public String name;
+    private String name;
 
     private KeyType keyType = KeyType.NULL;
 
     /**
      * The Type.
      */
-    public int type;
+    private int type;
 
     /**
      * The Value.
      */
-    public Object value;
+    private Object value;
 
     /**
      * Instantiates a new Field.
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java
index 33fbc25630265200c76b885b46e6f54b8085b5a1..e58ca92ec755d8cade5ff95bf1f09cc27fda3113 100755
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/Row.java
@@ -65,7 +65,7 @@ public class Row {
     /**
      * Primary keys list.
      *
-     * @return the list
+     * @return the Primary keys list
      */
     public List<Field> primaryKeys() {
         List<Field> pkFields = new ArrayList<>();
@@ -79,4 +79,19 @@ public class Row {
         }
         return pkFields;
     }
+
+    /**
+     * Non-primary keys list.
+     *
+     * @return the non-primary list
+     */
+    public List<Field> nonPrimaryKeys() {
+        List<Field> nonPkFields = new ArrayList<>();
+        for (Field field : fields) {
+            if (KeyType.PrimaryKey != field.getKeyType()) {
+                nonPkFields.add(field);
+            }
+        }
+        return nonPkFields;
+    }
 }
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java
index 7f4d3d6be31e31d6740e50285099b45becc506ad..116e013b7058947dce588c19ebf82ff4bc95df27 100755
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMeta.java
@@ -59,12 +59,11 @@ public class TableMeta {
      * @return the column meta
      */
     public ColumnMeta getColumnMeta(String colName) {
-        String s = colName;
-        ColumnMeta col = allColumns.get(s);
+        ColumnMeta col = allColumns.get(colName);
         if (col == null) {
             if (colName.charAt(0) == '`') {
-                col = allColumns.get(s.substring(1, colName.length() - 1));
-            } else { col = allColumns.get("`" + s + "`"); }
+                col = allColumns.get(colName.substring(1, colName.length() - 1));
+            } else { col = allColumns.get("`" + colName + "`"); }
         }
         return col;
     }
@@ -96,7 +95,7 @@ public class TableMeta {
         // TODO: how about auto increment but not pk?
         for (Entry<String, ColumnMeta> entry : allColumns.entrySet()) {
             ColumnMeta col = entry.getValue();
-            if ("YES".equalsIgnoreCase(col.getIsAutoincrement()) == true) {
+            if ("YES".equalsIgnoreCase(col.getIsAutoincrement())) {
                 return col;
             }
         }
@@ -133,13 +132,11 @@ public class TableMeta {
      */
     @SuppressWarnings("serial")
     public List<String> getPrimaryKeyOnlyName() {
-        return new ArrayList<String>() {
-            {
-                for (Entry<String, ColumnMeta> entry : getPrimaryKeyMap().entrySet()) {
-                    add(entry.getKey());
-                }
-            }
-        };
+        List<String> list = new ArrayList<>();
+        for (Entry<String, ColumnMeta> entry : getPrimaryKeyMap().entrySet()) {
+            list.add(entry.getKey());
+        }
+        return list;
     }
 
     /**
@@ -183,7 +180,7 @@ public class TableMeta {
         boolean flag = true;
         Map<String, ColumnMeta> allColumns = getAllColumns();
         for (Entry<String, ColumnMeta> entry : allColumns.entrySet()) {
-            if (flag == true) {
+            if (flag) {
                 flag = false;
             } else {
                 sb.append(",");
@@ -218,7 +215,7 @@ public class TableMeta {
                     sb.append(String.format("KEY `%s`", index.getIndexName()));
                     break;
                 case PRIMARY:
-                    sb.append(String.format("PRIMARY KEY"));
+                    sb.append("PRIMARY KEY");
                     break;
                 case Unique:
                     sb.append(String.format("UNIQUE KEY `%s`", index.getIndexName()));
@@ -230,7 +227,7 @@ public class TableMeta {
             sb.append(" (");
             boolean f = true;
             for (ColumnMeta c : index.getValues()) {
-                if (f == true) {
+                if (f) {
                     f = false;
                 } else {
                     sb.append(",");
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java
index ff87d6c9ba6e8b37c17b8bbe468a79824b3d26b7..a4010b059a9bac6721ad413702bafbc72c02cd06 100755
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableMetaCache.java
@@ -15,24 +15,24 @@
  */
 package io.seata.rm.datasource.sql.struct;
 
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
 import com.alibaba.druid.util.StringUtils;
+import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
 import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.core.context.RootContext;
 import io.seata.rm.datasource.AbstractConnectionProxy;
 import io.seata.rm.datasource.DataSourceProxy;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.concurrent.TimeUnit;
 
 /**
  * The type Table meta cache.
@@ -45,8 +45,10 @@ public class TableMetaCache {
 
     private static final long EXPIRE_TIME = 900 * 1000;
 
-    private static final Cache<String, TableMeta> TABLE_META_CACHE = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE)
-        .expireAfterWrite(EXPIRE_TIME, TimeUnit.MILLISECONDS).softValues().build();
+    private static final Cache<String, TableMeta> TABLE_META_CACHE = Caffeine.newBuilder().maximumSize(CACHE_SIZE)
+            .expireAfterWrite(EXPIRE_TIME, TimeUnit.MILLISECONDS).softValues().build();
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(TableMetaCache.class);
 
     /**
      * Gets table meta.
@@ -62,17 +64,16 @@ public class TableMetaCache {
 
         String dataSourceKey = dataSourceProxy.getResourceId();
 
-        TableMeta tmeta = null;
+        TableMeta tmeta;
         final String key = dataSourceKey + "." + tableName;
-        try {
-            tmeta = TABLE_META_CACHE.get(key, new Callable<TableMeta>() {
-                @Override
-                public TableMeta call() throws Exception {
-                    return fetchSchema(dataSourceProxy.getTargetDataSource(), tableName);
-                }
-            });
-        } catch (ExecutionException e) {
-        }
+        tmeta = TABLE_META_CACHE.get(key, mappingFunction -> {
+            try {
+                return fetchSchema(dataSourceProxy.getTargetDataSource(), tableName);
+            } catch (SQLException e) {
+                LOGGER.error("get cache error !", e);
+                return null;
+            }
+        });
 
         if (tmeta == null) {
             try {
@@ -92,10 +93,10 @@ public class TableMetaCache {
     }
 
     private static TableMeta fetchSchemeInDefaultWay(DataSource dataSource, String tableName)
-        throws SQLException {
+            throws SQLException {
         Connection conn = null;
-        java.sql.Statement stmt = null;
-        java.sql.ResultSet rs = null;
+        Statement stmt = null;
+        ResultSet rs = null;
         try {
             conn = dataSource.getConnection();
             stmt = conn.createStatement();
@@ -107,7 +108,7 @@ public class TableMetaCache {
             return resultSetMetaToSchema(rsmd, dbmd, tableName);
         } catch (Exception e) {
             if (e instanceof SQLException) {
-                throw ((SQLException)e);
+                throw ((SQLException) e);
             }
             throw new SQLException("Failed to fetch schema of " + tableName, e);
 
@@ -125,9 +126,7 @@ public class TableMetaCache {
     }
 
     private static TableMeta resultSetMetaToSchema(java.sql.ResultSet rs2, AbstractConnectionProxy conn,
-                                                   String tablename) throws SQLException {
-        String tableName = tablename;
-
+                                                   String tableName) throws SQLException {
         TableMeta tm = new TableMeta();
         tm.setTableName(tableName);
         while (rs2.next()) {
@@ -155,9 +154,9 @@ public class TableMetaCache {
         try {
             stmt = conn.getTargetConnection().createStatement();
             rs1 = stmt.executeQuery(
-                "select a.constraint_name,  a.column_name from user_cons_columns a, user_constraints b  where a"
-                    + ".constraint_name = b.constraint_name and b.constraint_type = 'P' and a.table_name ='"
-                    + tableName + "'");
+                    "select a.constraint_name,  a.column_name from user_cons_columns a, user_constraints b  where a"
+                            + ".constraint_name = b.constraint_name and b.constraint_type = 'P' and a.table_name ='"
+                            + tableName + "'");
             while (rs1.next()) {
                 String indexName = rs1.getString(1);
                 String colName = rs1.getString(2);
@@ -188,14 +187,14 @@ public class TableMetaCache {
     }
 
     private static TableMeta resultSetMetaToSchema(ResultSetMetaData rsmd, DatabaseMetaData dbmd, String tableName)
-        throws SQLException {
+            throws SQLException {
         String schemaName = rsmd.getSchemaName(1);
         String catalogName = rsmd.getCatalogName(1);
 
         TableMeta tm = new TableMeta();
         tm.setTableName(tableName);
 
-        java.sql.ResultSet rs1 = dbmd.getColumns(catalogName, schemaName, tableName, "%");
+        ResultSet rs1 = dbmd.getColumns(catalogName, schemaName, tableName, "%");
         while (rs1.next()) {
             ColumnMeta col = new ColumnMeta();
             col.setTableCat(rs1.getString("TABLE_CAT"));
@@ -220,7 +219,7 @@ public class TableMetaCache {
             tm.getAllColumns().put(col.getColumnName(), col);
         }
 
-        java.sql.ResultSet rs2 = dbmd.getIndexInfo(catalogName, schemaName, tableName, false, true);
+        ResultSet rs2 = dbmd.getIndexInfo(catalogName, schemaName, tableName, false, true);
         String indexName = "";
         while (rs2.next()) {
             indexName = rs2.getString("INDEX_NAME");
@@ -242,9 +241,9 @@ public class TableMetaCache {
                 index.setCardinality(rs2.getInt("CARDINALITY"));
                 index.getValues().add(col);
                 if ("PRIMARY".equalsIgnoreCase(indexName) || indexName.equalsIgnoreCase(
-                    rsmd.getTableName(1) + "_pkey")) {
+                        rsmd.getTableName(1) + "_pkey")) {
                     index.setIndextype(IndexType.PRIMARY);
-                } else if (index.isNonUnique() == false) {
+                } else if (!index.isNonUnique()) {
                     index.setIndextype(IndexType.Unique);
                 } else {
                     index.setIndextype(IndexType.Normal);
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java
index 6bd17138240b0b322e608a5ef85251f2a023787f..a4412da86946777403d666b5d69d3208d7e631a2 100755
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/sql/struct/TableRecords.java
@@ -128,19 +128,17 @@ public class TableRecords {
      */
     public List<Field> pkRows() {
         final String pkName = getTableMeta().getPkName();
-        return new ArrayList<Field>() {
-            {
-                for (Row row : rows) {
-                    List<Field> fields = row.getFields();
-                    for (Field field : fields) {
-                        if (field.getName().equalsIgnoreCase(pkName)) {
-                            add(field);
-                            break;
-                        }
-                    }
+        List<Field> pkRows = new ArrayList<>();
+        for (Row row : rows) {
+            List<Field> fields = row.getFields();
+            for (Field field : fields) {
+                if (field.getName().equalsIgnoreCase(pkName)) {
+                    pkRows.add(field);
+                    break;
                 }
             }
-        };
+        }
+        return pkRows;
     }
 
     /**
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java
index a4a52b3001285a665750d57a4ae1b6b3b3efdbba..779da87c8d18ce3ef524c158af330c1167cfe475 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java
@@ -20,6 +20,7 @@ import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.util.ArrayList;
 
+import io.seata.rm.datasource.DataCompareUtils;
 import io.seata.rm.datasource.sql.struct.Field;
 import io.seata.rm.datasource.sql.struct.KeyType;
 import io.seata.rm.datasource.sql.struct.Row;
@@ -29,6 +30,7 @@ import io.seata.rm.datasource.sql.struct.TableRecords;
  * The type Abstract undo executor.
  *
  * @author sharajava
+ * @author Geng Zhang
  */
 public abstract class AbstractUndoExecutor {
 
@@ -53,6 +55,15 @@ public abstract class AbstractUndoExecutor {
         this.sqlUndoLog = sqlUndoLog;
     }
 
+    /**
+     * Gets sql undo log.
+     *
+     * @return the sql undo log
+     */
+    public SQLUndoLog getSqlUndoLog() {
+        return sqlUndoLog;
+    }
+
     /**
      * Execute on.
      *
@@ -60,8 +71,12 @@ public abstract class AbstractUndoExecutor {
      * @throws SQLException the sql exception
      */
     public void executeOn(Connection conn) throws SQLException {
-        dataValidation(conn);
 
+        // no need undo if the before data snapshot is equivalent to the after data snapshot.
+        if (DataCompareUtils.isRecordsEquals(sqlUndoLog.getBeforeImage(), sqlUndoLog.getAfterImage())) {
+            return;
+        }
+        dataValidation(conn);
         try {
             String undoSQL = buildUndoSQL();
 
@@ -87,7 +102,7 @@ public abstract class AbstractUndoExecutor {
 
         } catch (Exception ex) {
             if (ex instanceof SQLException) {
-                throw (SQLException)ex;
+                throw (SQLException) ex;
             } else {
                 throw new SQLException(ex);
             }
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java
index c13bbc52e3330d43dd03e888cf239450b382a974..8cb7ffe0e50066aaccfcc7c2e31ecbc44668cb48 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutor.java
@@ -15,21 +15,19 @@
  */
 package io.seata.rm.datasource.undo.mysql;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import com.alibaba.druid.util.JdbcConstants;
 import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.rm.datasource.sql.struct.Field;
-import io.seata.rm.datasource.sql.struct.KeyType;
 import io.seata.rm.datasource.sql.struct.Row;
 import io.seata.rm.datasource.sql.struct.TableRecords;
 import io.seata.rm.datasource.undo.AbstractUndoExecutor;
 import io.seata.rm.datasource.undo.KeywordChecker;
 import io.seata.rm.datasource.undo.KeywordCheckerFactory;
 import io.seata.rm.datasource.undo.SQLUndoLog;
-import io.seata.rm.datasource.undo.AbstractUndoExecutor;
-import io.seata.rm.datasource.undo.KeywordChecker;
-import io.seata.rm.datasource.undo.KeywordCheckerFactory;
 
 /**
  * The type My sql undo delete executor.
@@ -47,6 +45,19 @@ public class MySQLUndoDeleteExecutor extends AbstractUndoExecutor {
         super(sqlUndoLog);
     }
 
+    /**
+     * INSERT INTO a (x, y, z, pk) VALUES (?, ?, ?, ?)
+     */
+    private static final String INSERT_SQL_TEMPLATE = "INSERT INTO %s (%s) VALUES (%s)";
+
+    /**
+     * Undo delete.
+     *
+     * Notice: PK is at last one.
+     * @see AbstractUndoExecutor#undoPrepare
+     *
+     * @return sql
+     */
     @Override
     protected String buildUndoSQL() {
         KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL);
@@ -56,38 +67,19 @@ public class MySQLUndoDeleteExecutor extends AbstractUndoExecutor {
             throw new ShouldNeverHappenException("Invalid UNDO LOG");
         }
         Row row = beforeImageRows.get(0);
+        List<Field> fields = new ArrayList<>(row.nonPrimaryKeys());
+        Field pkField = row.primaryKeys().get(0);
+        // PK is at last one.
+        fields.add(pkField);
 
-        StringBuffer insertColumns = new StringBuffer();
-        StringBuffer insertValues = new StringBuffer();
-        Field pkField = null;
-        boolean first = true;
-        for (Field field : row.getFields()) {
-            if (field.getKeyType() == KeyType.PrimaryKey) {
-                pkField = field;
-                continue;
-            } else {
-                if (first) {
-                    first = false;
-                } else {
-                    insertColumns.append(", ");
-                    insertValues.append(", ");
-                }
-                insertColumns.append(keywordChecker.checkAndReplace(field.getName()));
-                insertValues.append("?");
-            }
-
-        }
-        if (first) {
-            first = false;
-        } else {
-            insertColumns.append(", ");
-            insertValues.append(", ");
-        }
-        insertColumns.append(keywordChecker.checkAndReplace(pkField.getName()));
-        insertValues.append("?");
+        String insertColumns = fields.stream()
+            .map(field -> keywordChecker.checkAndReplace(field.getName()))
+            .collect(Collectors.joining(", "));
+        String insertValues = fields.stream().map(field -> "?")
+            .collect(Collectors.joining(", "));
 
-        return "INSERT INTO " + keywordChecker.checkAndReplace(sqlUndoLog.getTableName()) + "(" + insertColumns
-            .toString() + ") VALUES (" + insertValues.toString() + ")";
+        return String.format(INSERT_SQL_TEMPLATE, keywordChecker.checkAndReplace(sqlUndoLog.getTableName()),
+                             insertColumns, insertValues);
     }
 
     @Override
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java
index 9975b137b24f04ef930d2406e14f436f05dd357d..481427745d0b5d4e7ba9f634c39e28b4d8abf932 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutor.java
@@ -23,16 +23,12 @@ import java.util.List;
 import com.alibaba.druid.util.JdbcConstants;
 import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.rm.datasource.sql.struct.Field;
-import io.seata.rm.datasource.sql.struct.KeyType;
 import io.seata.rm.datasource.sql.struct.Row;
 import io.seata.rm.datasource.sql.struct.TableRecords;
 import io.seata.rm.datasource.undo.AbstractUndoExecutor;
 import io.seata.rm.datasource.undo.KeywordChecker;
 import io.seata.rm.datasource.undo.KeywordCheckerFactory;
 import io.seata.rm.datasource.undo.SQLUndoLog;
-import io.seata.rm.datasource.undo.AbstractUndoExecutor;
-import io.seata.rm.datasource.undo.KeywordChecker;
-import io.seata.rm.datasource.undo.KeywordCheckerFactory;
 
 /**
  * The type My sql undo insert executor.
@@ -41,6 +37,16 @@ import io.seata.rm.datasource.undo.KeywordCheckerFactory;
  */
 public class MySQLUndoInsertExecutor extends AbstractUndoExecutor {
 
+    /**
+     * DELETE FROM a WHERE pk = ?
+     */
+    private static final String DELETE_SQL_TEMPLATE = "DELETE FROM %s WHERE %s = ?";
+
+    /**
+     * Undo Inset.
+     *
+     * @return sql
+     */
     @Override
     protected String buildUndoSQL() {
         KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL);
@@ -50,17 +56,10 @@ public class MySQLUndoInsertExecutor extends AbstractUndoExecutor {
             throw new ShouldNeverHappenException("Invalid UNDO LOG");
         }
         Row row = afterImageRows.get(0);
-        StringBuffer mainSQL = new StringBuffer(
-            "DELETE FROM " + keywordChecker.checkAndReplace(sqlUndoLog.getTableName()));
-        StringBuffer where = new StringBuffer(" WHERE ");
-        boolean first = true;
-        for (Field field : row.getFields()) {
-            if (field.getKeyType() == KeyType.PrimaryKey) {
-                where.append(keywordChecker.checkAndReplace(field.getName()) + " = ?");
-            }
-
-        }
-        return mainSQL.append(where).toString();
+        Field pkField = row.primaryKeys().get(0);
+        return String.format(DELETE_SQL_TEMPLATE,
+                             keywordChecker.checkAndReplace(sqlUndoLog.getTableName()),
+                             keywordChecker.checkAndReplace(pkField.getName()));
     }
 
     @Override
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java
index a7398fe9cec0909b2845162a2e3399c801a323ab..676f4d34a38bdb946eb1832252ae8ccaf8c401d7 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutor.java
@@ -15,21 +15,18 @@
  */
 package io.seata.rm.datasource.undo.mysql;
 
-import java.util.List;
-
 import com.alibaba.druid.util.JdbcConstants;
 import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.rm.datasource.sql.struct.Field;
-import io.seata.rm.datasource.sql.struct.KeyType;
 import io.seata.rm.datasource.sql.struct.Row;
 import io.seata.rm.datasource.sql.struct.TableRecords;
 import io.seata.rm.datasource.undo.AbstractUndoExecutor;
 import io.seata.rm.datasource.undo.KeywordChecker;
 import io.seata.rm.datasource.undo.KeywordCheckerFactory;
 import io.seata.rm.datasource.undo.SQLUndoLog;
-import io.seata.rm.datasource.undo.AbstractUndoExecutor;
-import io.seata.rm.datasource.undo.KeywordChecker;
-import io.seata.rm.datasource.undo.KeywordCheckerFactory;
+
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * The type My sql undo update executor.
@@ -38,6 +35,16 @@ import io.seata.rm.datasource.undo.KeywordCheckerFactory;
  */
 public class MySQLUndoUpdateExecutor extends AbstractUndoExecutor {
 
+    /**
+     * UPDATE a SET x = ?, y = ?, z = ? WHERE pk = ?
+     */
+    private static final String UPDATE_SQL_TEMPLATE = "UPDATE %s SET %s WHERE %s = ?";
+
+    /**
+     * Undo Update.
+     *
+     * @return sql
+     */
     @Override
     protected String buildUndoSQL() {
         KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL);
@@ -47,24 +54,13 @@ public class MySQLUndoUpdateExecutor extends AbstractUndoExecutor {
             throw new ShouldNeverHappenException("Invalid UNDO LOG"); // TODO
         }
         Row row = beforeImageRows.get(0);
-        StringBuffer mainSQL = new StringBuffer(
-            "UPDATE " + keywordChecker.checkAndReplace(sqlUndoLog.getTableName()) + " SET ");
-        StringBuffer where = new StringBuffer(" WHERE ");
-        boolean first = true;
-        for (Field field : row.getFields()) {
-            if (field.getKeyType() == KeyType.PrimaryKey) {
-                where.append(keywordChecker.checkAndReplace(field.getName()) + " = ?");
-            } else {
-                if (first) {
-                    first = false;
-                } else {
-                    mainSQL.append(", ");
-                }
-                mainSQL.append(keywordChecker.checkAndReplace(field.getName()) + " = ?");
-            }
-
-        }
-        return mainSQL.append(where).toString();
+        Field pkField = row.primaryKeys().get(0);
+        List<Field> nonPkFields = row.nonPrimaryKeys();
+        String updateColumns = nonPkFields.stream()
+            .map(field -> keywordChecker.checkAndReplace(field.getName()) + " = ?")
+            .collect(Collectors.joining(", "));
+        return String.format(UPDATE_SQL_TEMPLATE, keywordChecker.checkAndReplace(sqlUndoLog.getTableName()),
+                             updateColumns, keywordChecker.checkAndReplace(pkField.getName()));
     }
 
     /**
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java
index 82f1de1820df542df7d2899f7cdb24357b718575..f759a06c4249aeeee6b55ba25f21e7d595d224cb 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordChecker.java
@@ -15,7 +15,6 @@
  */
 package io.seata.rm.datasource.undo.mysql.keyword;
 
-import io.seata.rm.datasource.undo.KeywordChecker;
 import io.seata.rm.datasource.undo.KeywordChecker;
 
 import java.util.Arrays;
diff --git a/rm-datasource/src/test/java/io/seata/rm/GlobalLockLocalTransactionlTemplateTest.java b/rm-datasource/src/test/java/io/seata/rm/GlobalLockLocalTransactionlTemplateTest.java
index d7fafa850a7edb024930ceb8fe4a316163bf7d06..122f52a085a24bbd66b32736a4f11a7e739db0e9 100644
--- a/rm-datasource/src/test/java/io/seata/rm/GlobalLockLocalTransactionlTemplateTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/GlobalLockLocalTransactionlTemplateTest.java
@@ -15,12 +15,9 @@
  */
 package io.seata.rm;
 
-import java.util.concurrent.Callable;
-
 import io.seata.core.context.RootContext;
-
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * check GlobalLockLocalTransactionlTemplate
@@ -39,16 +36,11 @@ public class GlobalLockLocalTransactionlTemplateTest {
 
         GlobalLockTemplate<Object> template = new GlobalLockTemplate<Object>();
 
-        template.execute(new Callable<Object>() {
-
-            @Override
-            public Object call() throws Exception {
-                Assert.assertTrue("lock flag not set!", RootContext.requireGlobalLock());
-                return null;
-            }
+        template.execute(() -> {
+            Assertions.assertTrue(RootContext.requireGlobalLock(), "lock flag not set!");
+            return null;
         });
 
-        Assert.assertTrue("lock flag not clean!", !RootContext.requireGlobalLock());
-
+        Assertions.assertTrue(!RootContext.requireGlobalLock(), "lock flag not clean!");
     }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..039b65e71f8294bfd5e2d7d7b89a9344550c5e7d
--- /dev/null
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/DataCompareUtilsTest.java
@@ -0,0 +1,154 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.rm.datasource;
+
+import io.seata.rm.datasource.sql.struct.Field;
+import io.seata.rm.datasource.sql.struct.Row;
+import io.seata.rm.datasource.sql.struct.TableMeta;
+import io.seata.rm.datasource.sql.struct.TableRecords;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Geng Zhang
+ */
+public class DataCompareUtilsTest {
+
+    @Test
+    public void isFieldEquals() {
+        Field field0 = new Field("name", 0, "111");
+        Field field1 = new Field("name", 1, "111");
+        Field field2 = new Field("name", 0, "222");
+        Field field3 = new Field("age", 0, "222");
+        Field field4 = new Field("name", 0, null);
+
+        Assertions.assertFalse(DataCompareUtils.isFieldEquals(field0, null));
+        Assertions.assertFalse(DataCompareUtils.isFieldEquals(null, field0));
+        Assertions.assertFalse(DataCompareUtils.isFieldEquals(field0, field1));
+        Assertions.assertFalse(DataCompareUtils.isFieldEquals(field0, field2));
+        Assertions.assertFalse(DataCompareUtils.isFieldEquals(field0, field3));
+        Assertions.assertFalse(DataCompareUtils.isFieldEquals(field0, field4));
+
+        Field field10 = new Field("Name", 0, "111");
+        Field field11 = new Field("Name", 0, null);
+        Assertions.assertTrue(DataCompareUtils.isFieldEquals(field0, field10));
+        Assertions.assertTrue(DataCompareUtils.isFieldEquals(field4, field11));
+    }
+
+    @Test
+    public void isRecordsEquals() {
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(tableMeta.getPkName()).thenReturn("pk");
+        Mockito.when(tableMeta.getTableName()).thenReturn("table_name");
+
+        TableRecords beforeImage = new TableRecords();
+        beforeImage.setTableName("table_name");
+        beforeImage.setTableMeta(tableMeta);
+
+        List<Row> rows = new ArrayList<>();
+        Row row = new Row();
+        Field field01 = addField(row,"pk", 1, "12345");
+        Field field02 = addField(row,"age", 1, "18");
+        rows.add(row);
+        beforeImage.setRows(rows);
+
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, null));
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(null, beforeImage));
+
+        TableRecords afterImage = new TableRecords();
+        afterImage.setTableName("table_name1"); // wrong table name
+        afterImage.setTableMeta(tableMeta);
+
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+        afterImage.setTableName("table_name");
+
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+
+        List<Row> rows2 = new ArrayList<>();
+        Row row2 = new Row();
+        Field field11 = addField(row2,"pk", 1, "12345");
+        Field field12 = addField(row2,"age", 1, "18");
+        rows2.add(row2);
+        afterImage.setRows(rows2);
+        Assertions.assertTrue(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+
+        field11.setValue("23456");
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+        field11.setValue("12345");
+
+        field12.setName("sex");
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+        field12.setName("age");
+
+        field12.setValue("19");
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+        field12.setName("18");
+
+        Field field3 = new Field("pk", 1, "12346");
+        Row row3 = new Row();
+        row3.add(field3);
+        rows2.add(row3);
+        Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+        
+
+        beforeImage.setRows(new ArrayList<>());
+        afterImage.setRows(new ArrayList<>());
+        Assertions.assertTrue(DataCompareUtils.isRecordsEquals(beforeImage, afterImage));
+    }
+    
+    private Field addField(Row row, String name, int type, Object value){
+        Field field = new Field(name, type, value);
+        row.add(field);
+        return field;
+    }
+
+    @Test
+    public void isRowsEquals() {
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(tableMeta.getPkName()).thenReturn("pk");
+        Mockito.when(tableMeta.getTableName()).thenReturn("table_name");
+
+        List<Row> rows = new ArrayList<>();
+        Field field = new Field("pk", 1, "12345");
+        Row row = new Row();
+        row.add(field);
+        rows.add(row);
+
+        Assertions.assertFalse(DataCompareUtils.isRowsEquals(tableMeta, rows, null));
+        Assertions.assertFalse(DataCompareUtils.isRowsEquals(tableMeta, null, rows));
+
+        List<Row> rows2 = new ArrayList<>();
+        Field field2 = new Field("pk", 1, "12345");
+        Row row2 = new Row();
+        row2.add(field2);
+        rows2.add(row2);
+        Assertions.assertTrue(DataCompareUtils.isRowsEquals(tableMeta, rows, rows2));
+
+        field.setValue("23456");
+        Assertions.assertFalse(DataCompareUtils.isRowsEquals(tableMeta, rows, rows2));
+        field.setValue("12345");
+
+        Field field3 = new Field("pk", 1, "12346");
+        Row row3 = new Row();
+        row3.add(field3);
+        rows2.add(row3);
+        Assertions.assertFalse(DataCompareUtils.isRowsEquals(tableMeta, rows, rows2));
+    }
+}
\ No newline at end of file
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/SQLVisitorFactoryTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/SQLVisitorFactoryTest.java
index a9899938d20b9c31bbe3c5b9f2ae0b6b585138e5..c294bf5ac73d6c050f09b0d940686f35678ec9c2 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/SQLVisitorFactoryTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/SQLVisitorFactoryTest.java
@@ -20,8 +20,8 @@ import io.seata.rm.datasource.sql.SQLRecognizer;
 import io.seata.rm.datasource.sql.SQLVisitorFactory;
 import io.seata.rm.datasource.sql.druid.MySQLSelectForUpdateRecognizer;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Sql visitor factory test.
@@ -36,10 +36,10 @@ public class SQLVisitorFactoryTest {
         String dbType = JdbcConstants.MYSQL;
         String sql = "select a, b, c from t1 where id = 9";
         SQLRecognizer recognizer = SQLVisitorFactory.get(sql, dbType);
-        Assert.assertNull(recognizer);
+        Assertions.assertNull(recognizer);
 
         sql = sql + " for update";
         recognizer = SQLVisitorFactory.get(sql, dbType);
-        Assert.assertTrue(recognizer instanceof MySQLSelectForUpdateRecognizer);
+        Assertions.assertTrue(recognizer instanceof MySQLSelectForUpdateRecognizer);
     }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
index 9c45bae1943c8afb834fcd87fb501444c1298442..cf4700c2ecfd8eb6351061583ed83faeb6994acf 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
@@ -15,20 +15,19 @@
  */
 package io.seata.rm.datasource.exec;
 
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
 import io.seata.rm.GlobalLockTemplate;
 import io.seata.rm.datasource.ConnectionProxy;
 import io.seata.rm.datasource.StatementProxy;
 import io.seata.rm.datasource.sql.struct.Field;
 import io.seata.rm.datasource.sql.struct.TableMeta;
 import io.seata.rm.datasource.sql.struct.TableRecords;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
-import org.junit.Assert;
-import org.junit.Test;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -46,28 +45,24 @@ public class BaseTransactionalExecutorTest {
         StatementProxy statementProxy = new StatementProxy<>(connectionProxy, null);
 
         BaseTransactionalExecutor<Object, Statement> baseTransactionalExecutor
-            = new BaseTransactionalExecutor<Object, Statement>(statementProxy, null, null) {
+                = new BaseTransactionalExecutor<Object, Statement>(statementProxy, null, null) {
             @Override
-            protected Object doExecute(Object... args) throws Throwable {
+            protected Object doExecute(Object... args) {
                 return null;
             }
         };
         GlobalLockTemplate<Object> globalLockLocalTransactionalTemplate = new GlobalLockTemplate<>();
 
         // not in global lock context
-        new Callable<Object>() {
-
-            @Override
-            public Object call() throws Exception {
-                try {
-                    baseTransactionalExecutor.execute(new Object());
-                    Assert.assertTrue("conectionContext set!", !connectionProxy.isGlobalLockRequire());
-                } catch (Throwable e) {
-                    throw new RuntimeException(e);
-                }
-                return null;
+        ((Callable<Object>) () -> {
+            try {
+                baseTransactionalExecutor.execute(new Object());
+                Assertions.assertTrue(!connectionProxy.isGlobalLockRequire(), "conectionContext set!");
+            } catch (Throwable e) {
+                throw new RuntimeException(e);
             }
-        }.call();
+            return null;
+        }).call();
 
         //in global lock context
         globalLockLocalTransactionalTemplate.execute(new Callable<Object>() {
@@ -76,7 +71,7 @@ public class BaseTransactionalExecutorTest {
             public Object call() throws Exception {
                 try {
                     baseTransactionalExecutor.execute(new Object());
-                    Assert.assertTrue("conectionContext not set!", connectionProxy.isGlobalLockRequire());
+                    Assertions.assertTrue(connectionProxy.isGlobalLockRequire(), "conectionContext not set!");
                 } catch (Throwable e) {
                     throw new RuntimeException(e);
                 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java
index fac24ca17846389d92cf40ff5cbffb40001c49c6..beb7c5ca793ac5e1dc6f040fb450def21c4278f6 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/InsertExecutorTest.java
@@ -19,10 +19,14 @@ import io.seata.common.exception.NotSupportYetException;
 import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.rm.datasource.PreparedStatementProxy;
 import io.seata.rm.datasource.sql.SQLInsertRecognizer;
-import io.seata.rm.datasource.sql.struct.*;
-import org.assertj.core.api.Assertions;
-import org.junit.Before;
-import org.junit.Test;
+import io.seata.rm.datasource.sql.struct.ColumnMeta;
+import io.seata.rm.datasource.sql.struct.Null;
+import io.seata.rm.datasource.sql.struct.Row;
+import io.seata.rm.datasource.sql.struct.TableMeta;
+import io.seata.rm.datasource.sql.struct.TableRecords;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
 import java.sql.PreparedStatement;
@@ -33,12 +37,11 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
 
 /**
  * @author guoyao
@@ -61,12 +64,12 @@ public class InsertExecutorTest {
 
     private InsertExecutor insertExecutor;
 
-    @Before
+    @BeforeEach
     public void init() {
         statementProxy = mock(PreparedStatementProxy.class);
         statementCallback = mock(StatementCallback.class);
         sqlInsertRecognizer = mock(SQLInsertRecognizer.class);
-        tableMeta =  mock(TableMeta.class);
+        tableMeta = mock(TableMeta.class);
         insertExecutor = Mockito.spy(new InsertExecutor(statementProxy, statementCallback, sqlInsertRecognizer));
     }
 
@@ -74,17 +77,16 @@ public class InsertExecutorTest {
     public void testBeforeImage() throws SQLException {
         doReturn(tableMeta).when(insertExecutor).getTableMeta();
         TableRecords tableRecords = insertExecutor.beforeImage();
-        Assertions.assertThat(tableRecords.getRows()).isEmpty();
-        Assertions.assertThat(tableRecords.size()).isEqualTo(0);
+        Assertions.assertEquals(tableRecords.size(), 0);
         try {
             tableRecords.add(new Row());
         } catch (Exception e) {
-            Assertions.assertThat(e instanceof UnsupportedOperationException).isTrue();
+            Assertions.assertTrue(e instanceof UnsupportedOperationException);
         }
         try {
             tableRecords.getTableMeta();
         } catch (Exception e) {
-            Assertions.assertThat(e instanceof UnsupportedOperationException).isTrue();
+            Assertions.assertTrue(e instanceof UnsupportedOperationException);
         }
     }
 
@@ -97,7 +99,7 @@ public class InsertExecutorTest {
         TableRecords tableRecords = new TableRecords();
         doReturn(tableRecords).when(insertExecutor).getTableRecords(pkValues);
         TableRecords resultTableRecords = insertExecutor.afterImage(new TableRecords());
-        Assertions.assertThat(resultTableRecords).isEqualTo(tableRecords);
+        Assertions.assertEquals(resultTableRecords, tableRecords);
     }
 
     @Test
@@ -109,17 +111,19 @@ public class InsertExecutorTest {
         TableRecords tableRecords = new TableRecords();
         doReturn(tableRecords).when(insertExecutor).getTableRecords(pkValues);
         TableRecords resultTableRecords = insertExecutor.afterImage(new TableRecords());
-        Assertions.assertThat(resultTableRecords).isEqualTo(tableRecords);
+        Assertions.assertEquals(resultTableRecords, tableRecords);
     }
 
-    @Test(expected = SQLException.class)
-    public void testAfterImage_Exception() throws SQLException {
-        doReturn(false).when(insertExecutor).containsPK();
-        List<Object> pkValues = new ArrayList<>();
-        pkValues.add(PK_VALUE);
-        doReturn(pkValues).when(insertExecutor).getPkValuesByAuto();
-        doReturn(null).when(insertExecutor).getTableRecords(pkValues);
-        insertExecutor.afterImage(new TableRecords());
+    @Test
+    public void testAfterImage_Exception() {
+        Assertions.assertThrows(SQLException.class, () -> {
+            doReturn(false).when(insertExecutor).containsPK();
+            List<Object> pkValues = new ArrayList<>();
+            pkValues.add(PK_VALUE);
+            doReturn(pkValues).when(insertExecutor).getPkValuesByAuto();
+            doReturn(null).when(insertExecutor).getTableRecords(pkValues);
+            insertExecutor.afterImage(new TableRecords());
+        });
     }
 
     @Test
@@ -127,9 +131,9 @@ public class InsertExecutorTest {
         List<String> insertColumns = mockInsertColumns();
         doReturn(tableMeta).when(insertExecutor).getTableMeta();
         when(tableMeta.containsPK(insertColumns)).thenReturn(true);
-        Assertions.assertThat(insertExecutor.containsPK()).isTrue();
+        Assertions.assertTrue(insertExecutor.containsPK());
         when(tableMeta.containsPK(insertColumns)).thenReturn(false);
-        Assertions.assertThat(insertExecutor.containsPK()).isFalse();
+        Assertions.assertFalse(insertExecutor.containsPK());
     }
 
     @Test
@@ -140,17 +144,19 @@ public class InsertExecutorTest {
         List<Object> pkValues = new ArrayList<>();
         pkValues.add(PK_VALUE);
         when(statementProxy.getParamsByIndex(0)).thenReturn(pkValues);
-        List pkValuesByColumn=insertExecutor.getPkValuesByColumn();
-        Assertions.assertThat(pkValuesByColumn).isEqualTo(pkValues);
+        List pkValuesByColumn = insertExecutor.getPkValuesByColumn();
+        Assertions.assertEquals(pkValuesByColumn, pkValues);
     }
 
-    @Test(expected = ShouldNeverHappenException.class)
-    public void testGetPkValuesByColumn_Exception() throws SQLException {
-        mockInsertColumns();
-        doReturn(tableMeta).when(insertExecutor).getTableMeta();
-        when(tableMeta.getPkName()).thenReturn(ID_COLUMN);
-        when(statementProxy.getParamsByIndex(0)).thenReturn(null);
-        insertExecutor.getPkValuesByColumn();
+    @Test
+    public void testGetPkValuesByColumn_Exception() {
+        Assertions.assertThrows(ShouldNeverHappenException.class, () -> {
+            mockInsertColumns();
+            doReturn(tableMeta).when(insertExecutor).getTableMeta();
+            when(tableMeta.getPkName()).thenReturn(ID_COLUMN);
+            when(statementProxy.getParamsByIndex(0)).thenReturn(null);
+            insertExecutor.getPkValuesByColumn();
+        });
     }
 
     @Test
@@ -168,42 +174,48 @@ public class InsertExecutorTest {
         List pkValuesByColumn = insertExecutor.getPkValuesByColumn();
         //pk value = Null so getPkValuesByAuto
         verify(insertExecutor).getPkValuesByAuto();
-        Assertions.assertThat(pkValuesByColumn).isEqualTo(pkValuesAuto);
+        Assertions.assertEquals(pkValuesByColumn, pkValuesAuto);
     }
 
-    @Test(expected = NotSupportYetException.class)
-    public void testGetPkValuesByAuto_NotSupportYetException() throws SQLException {
-        doReturn(tableMeta).when(insertExecutor).getTableMeta();
-        Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
-        columnMetaMap.put(ID_COLUMN, new ColumnMeta());
-        columnMetaMap.put(USER_ID_COLUMN, new ColumnMeta());
-        when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap);
-        insertExecutor.getPkValuesByAuto();
+    @Test
+    public void testGetPkValuesByAuto_NotSupportYetException() {
+        Assertions.assertThrows(NotSupportYetException.class, () -> {
+            doReturn(tableMeta).when(insertExecutor).getTableMeta();
+            Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
+            columnMetaMap.put(ID_COLUMN, new ColumnMeta());
+            columnMetaMap.put(USER_ID_COLUMN, new ColumnMeta());
+            when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap);
+            insertExecutor.getPkValuesByAuto();
+        });
     }
 
-    @Test(expected = ShouldNeverHappenException.class)
-    public void testGetPkValuesByAuto_ShouldNeverHappenException() throws SQLException {
-        doReturn(tableMeta).when(insertExecutor).getTableMeta();
-        Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
-        ColumnMeta columnMeta = mock(ColumnMeta.class);
-        columnMetaMap.put(ID_COLUMN, columnMeta);
-        when(columnMeta.isAutoincrement()).thenReturn(false);
-        when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap);
-        insertExecutor.getPkValuesByAuto();
+    @Test
+    public void testGetPkValuesByAuto_ShouldNeverHappenException() {
+        Assertions.assertThrows(ShouldNeverHappenException.class, () -> {
+            doReturn(tableMeta).when(insertExecutor).getTableMeta();
+            Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
+            ColumnMeta columnMeta = mock(ColumnMeta.class);
+            columnMetaMap.put(ID_COLUMN, columnMeta);
+            when(columnMeta.isAutoincrement()).thenReturn(false);
+            when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap);
+            insertExecutor.getPkValuesByAuto();
+        });
     }
 
-    @Test(expected = SQLException.class)
-    public void testGetPkValuesByAuto_SQLException() throws SQLException {
-        doReturn(tableMeta).when(insertExecutor).getTableMeta();
-        ColumnMeta columnMeta = mock(ColumnMeta.class);
-        Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
-        columnMetaMap.put(ID_COLUMN, columnMeta);
-        when(columnMeta.isAutoincrement()).thenReturn(true);
-        when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap);
-        PreparedStatement preparedStatement = mock(PreparedStatement.class);
-        when(statementProxy.getTargetStatement()).thenReturn(preparedStatement);
-        when(preparedStatement.getGeneratedKeys()).thenThrow(new SQLException());
-        insertExecutor.getPkValuesByAuto();
+    @Test
+    public void testGetPkValuesByAuto_SQLException() {
+        Assertions.assertThrows(SQLException.class, () -> {
+            doReturn(tableMeta).when(insertExecutor).getTableMeta();
+            ColumnMeta columnMeta = mock(ColumnMeta.class);
+            Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
+            columnMetaMap.put(ID_COLUMN, columnMeta);
+            when(columnMeta.isAutoincrement()).thenReturn(true);
+            when(tableMeta.getPrimaryKeyMap()).thenReturn(columnMetaMap);
+            PreparedStatement preparedStatement = mock(PreparedStatement.class);
+            when(statementProxy.getTargetStatement()).thenReturn(preparedStatement);
+            when(preparedStatement.getGeneratedKeys()).thenThrow(new SQLException());
+            insertExecutor.getPkValuesByAuto();
+        });
     }
 
     @Test
@@ -221,7 +233,7 @@ public class InsertExecutorTest {
         when(resultSet.next()).thenReturn(false);
         when(resultSet.getObject(1)).thenReturn(PK_VALUE);
         List pkValuesByAuto = insertExecutor.getPkValuesByAuto();
-        Assertions.assertThat(pkValuesByAuto).isEmpty();
+        Assertions.assertEquals(pkValuesByAuto.size(),0);
     }
 
     @Test
@@ -241,7 +253,7 @@ public class InsertExecutorTest {
         List<Object> pkValues = new ArrayList<>();
         pkValues.add(PK_VALUE);
         List pkValuesByAuto = insertExecutor.getPkValuesByAuto();
-        Assertions.assertThat(pkValuesByAuto).isEqualTo(pkValues);
+        Assertions.assertEquals(pkValuesByAuto, pkValues);
     }
 
     @Test
@@ -262,7 +274,7 @@ public class InsertExecutorTest {
         List<Object> pkValues = new ArrayList<>();
         pkValues.add(PK_VALUE);
         List pkValuesByAuto = insertExecutor.getPkValuesByAuto();
-        Assertions.assertThat(pkValuesByAuto).isEqualTo(pkValues);
+        Assertions.assertEquals(pkValuesByAuto, pkValues);
     }
 
     private List<String> mockInsertColumns() {
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizerTest.java
index 606bcb8f4ca70ad679b8f5e5c8dab633425fcebb..4c41904e16f45961ea34a31e5172cbb3d48ac384 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizerTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLDeleteRecognizerTest.java
@@ -16,13 +16,14 @@
 package io.seata.rm.datasource.sql.druid;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 
 import com.alibaba.druid.sql.ast.SQLStatement;
 import io.seata.rm.datasource.ParametersHolder;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type My sql delete recognizer test.
@@ -43,9 +44,9 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
-        Assert.assertEquals("id = 'id1'", mySQLDeleteRecognizer.getWhereCondition());
+        Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
+        Assertions.assertEquals("id = 'id1'", mySQLDeleteRecognizer.getWhereCondition());
     }
 
     /**
@@ -60,8 +61,8 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
+        Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
 
         // test overflow parameters
         ArrayList<Object> paramAppender = new ArrayList<>();
@@ -70,13 +71,75 @@ public class MySQLDeleteRecognizerTest extends AbstractMySQLRecognizerTest {
             public ArrayList<Object>[] getParameters() {
                 ArrayList<Object> idParam = new ArrayList<>();
                 idParam.add("id1");
-                ArrayList<Object> nameParam = new ArrayList<>();
-                nameParam.add("name1");
-                return new ArrayList[] {idParam, nameParam};
+                return new ArrayList[] {idParam};
             }
         }, paramAppender);
 
-        Assert.assertEquals(Collections.singletonList("id1"), paramAppender);
-        Assert.assertEquals("id = ?", whereCondition);
+        Assertions.assertEquals(Collections.singletonList("id1"), paramAppender);
+        Assertions.assertEquals("id = ?", whereCondition);
+    }
+
+    /**
+     * Delete recognizer test 2.
+     */
+    @Test
+    public void deleteRecognizerTest_2() {
+
+        String sql = "DELETE FROM t1 WHERE id IN (?, ?)";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
+
+        // test overflow parameters
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> idParam = new ArrayList<>();
+                idParam.add("id1");
+                ArrayList<Object> id2Param = new ArrayList<>();
+                id2Param.add("id2");
+                return new ArrayList[] {idParam, id2Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Arrays.asList("id1", "id2"), paramAppender);
+        Assertions.assertEquals("id IN (?, ?)", whereCondition);
+    }
+
+    /**
+     * Delete recognizer test 3.
+     */
+    @Test
+    public void deleteRecognizerTest_3() {
+
+        String sql = "DELETE FROM t1 WHERE id between ? AND ?";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
+
+        // test overflow parameters
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> idParam = new ArrayList<>();
+                idParam.add("id1");
+                ArrayList<Object> id2Param = new ArrayList<>();
+                id2Param.add("id2");
+                return new ArrayList[] {idParam, id2Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Arrays.asList("id1", "id2"), paramAppender);
+        Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
     }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLInsertRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLInsertRecognizerTest.java
index dfbdc42bd7de18d6a45fcefe061301c44e889719..5270af5b3f3b6e9d2bdb9859636cb9518d07ae5a 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLInsertRecognizerTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLInsertRecognizerTest.java
@@ -20,8 +20,8 @@ import java.util.Collections;
 
 import com.alibaba.druid.sql.ast.SQLStatement;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type My sql insert recognizer test.
@@ -42,11 +42,11 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLInsertRecognizer mySQLInsertRecognizer = new MySQLInsertRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLInsertRecognizer.getTableName());
-        Assert.assertEquals(Collections.singletonList("name"), mySQLInsertRecognizer.getInsertColumns());
-        Assert.assertEquals(1, mySQLInsertRecognizer.getInsertRows().size());
-        Assert.assertEquals(Collections.singletonList("name1"), mySQLInsertRecognizer.getInsertRows().get(0));
+        Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName());
+        Assertions.assertEquals(Collections.singletonList("name"), mySQLInsertRecognizer.getInsertColumns());
+        Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows().size());
+        Assertions.assertEquals(Collections.singletonList("name1"), mySQLInsertRecognizer.getInsertRows().get(0));
     }
 
     /**
@@ -61,11 +61,11 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLInsertRecognizer mySQLInsertRecognizer = new MySQLInsertRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLInsertRecognizer.getTableName());
-        Assert.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns());
-        Assert.assertEquals(1, mySQLInsertRecognizer.getInsertRows().size());
-        Assert.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows().get(0));
+        Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName());
+        Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns());
+        Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows().size());
+        Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows().get(0));
     }
 
     /**
@@ -80,13 +80,13 @@ public class MySQLInsertRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLInsertRecognizer mySQLInsertRecognizer = new MySQLInsertRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLInsertRecognizer.getTableName());
-        Assert.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns());
-        Assert.assertEquals(3, mySQLInsertRecognizer.getInsertRows().size());
-        Assert.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows().get(0));
-        Assert.assertEquals(Arrays.asList("name3", "name4"), mySQLInsertRecognizer.getInsertRows().get(1));
-        Assert.assertEquals(Arrays.asList("name5", "name6"), mySQLInsertRecognizer.getInsertRows().get(2));
+        Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName());
+        Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns());
+        Assertions.assertEquals(3, mySQLInsertRecognizer.getInsertRows().size());
+        Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows().get(0));
+        Assertions.assertEquals(Arrays.asList("name3", "name4"), mySQLInsertRecognizer.getInsertRows().get(1));
+        Assertions.assertEquals(Arrays.asList("name5", "name6"), mySQLInsertRecognizer.getInsertRows().get(2));
     }
 
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizerTest.java
index 58973e24ea5a540d7e2ed5583802233eeed8d1b1..26210773949558c34d274e282b5c2466ff99b557 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizerTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLSelectForUpdateRecognizerTest.java
@@ -16,13 +16,14 @@
 package io.seata.rm.datasource.sql.druid;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 
 import com.alibaba.druid.sql.ast.SQLStatement;
 import io.seata.rm.datasource.ParametersHolder;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type My sql select for update recognizer test.
@@ -41,9 +42,9 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT
 
         MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
-        Assert.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
     }
 
     /**
@@ -58,8 +59,8 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT
 
         MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
 
         ArrayList<Object> paramAppender = new ArrayList<>();
         String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
@@ -71,8 +72,8 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT
             }
         }, paramAppender);
 
-        Assert.assertEquals(Collections.singletonList("id1"), paramAppender);
-        Assert.assertEquals("id = ?", whereCondition);
+        Assertions.assertEquals(Collections.singletonList("id1"), paramAppender);
+        Assertions.assertEquals("id = ?", whereCondition);
     }
 
     /**
@@ -81,14 +82,76 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT
     @Test
     public void selectForUpdateRecognizerTest_3() {
 
-        String sql = "SELECT name1, name2 FROM t1 WHERE id1 = ? FOR UPDATE";
+        String sql = "SELECT name1, name2 FROM t1 WHERE id = ? FOR UPDATE";
 
         SQLStatement statement = getSQLStatement(sql);
 
         MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+
+        // test overflow parameters
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> id1Param = new ArrayList<>();
+                id1Param.add("id1");
+                return new ArrayList[] {id1Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Collections.singletonList("id1"), paramAppender);
+        Assertions.assertEquals("id = ?", whereCondition);
+    }
+
+    /**
+     * Select for update recognizer test 4.
+     */
+    @Test
+    public void selectForUpdateRecognizerTest_4() {
+
+        String sql = "SELECT name1, name2 FROM t1 WHERE id IN (?,?) FOR UPDATE";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+
+        // test overflow parameters
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> id1Param = new ArrayList<>();
+                id1Param.add("id1");
+                ArrayList<Object> id2Param = new ArrayList<>();
+                id2Param.add("id2");
+                return new ArrayList[] {id1Param, id2Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Arrays.asList("id1", "id2"), paramAppender);
+        Assertions.assertEquals("id IN (?, ?)", whereCondition);
+    }
+
+    /**
+     * Select for update recognizer test 5.
+     */
+    @Test
+    public void selectForUpdateRecognizerTest_5() {
+
+        String sql = "SELECT name1, name2 FROM t1 WHERE id between ? and ? FOR UPDATE";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
 
         // test overflow parameters
         ArrayList<Object> paramAppender = new ArrayList<>();
@@ -103,7 +166,7 @@ public class MySQLSelectForUpdateRecognizerTest extends AbstractMySQLRecognizerT
             }
         }, paramAppender);
 
-        Assert.assertEquals(Collections.singletonList("id1"), paramAppender);
-        Assert.assertEquals("id1 = ?", whereCondition);
+        Assertions.assertEquals(Arrays.asList("id1", "id2"), paramAppender);
+        Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
     }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizerTest.java
index b73b1a3f72b89dfc781cc3b8655be6077b4d8a97..27e803e040cf30de3a8cb407a0568515801f5c22 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizerTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/druid/MySQLUpdateRecognizerTest.java
@@ -16,13 +16,14 @@
 package io.seata.rm.datasource.sql.druid;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 
 import com.alibaba.druid.sql.ast.SQLStatement;
 import io.seata.rm.datasource.ParametersHolder;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type My sql update recognizer test.
@@ -41,12 +42,12 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
-        Assert.assertEquals(1, mySQLUpdateRecognizer.getUpdateColumns().size());
-        Assert.assertEquals("name", mySQLUpdateRecognizer.getUpdateColumns().get(0));
-        Assert.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
-        Assert.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(1, mySQLUpdateRecognizer.getUpdateColumns().size());
+        Assertions.assertEquals("name", mySQLUpdateRecognizer.getUpdateColumns().get(0));
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
+        Assertions.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
     }
 
     /**
@@ -61,14 +62,14 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
-        Assert.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
-        Assert.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
-        Assert.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
-        Assert.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
-        Assert.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
-        Assert.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
+        Assertions.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
     }
 
     /**
@@ -83,13 +84,13 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest {
 
         MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
 
-        Assert.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
-        Assert.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
-        Assert.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
-        Assert.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
-        Assert.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
-        Assert.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
-        Assert.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
 
         ArrayList<Object> paramAppender = new ArrayList<>();
         String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
@@ -97,12 +98,124 @@ public class MySQLUpdateRecognizerTest extends AbstractMySQLRecognizerTest {
             public ArrayList<Object>[] getParameters() {
                 ArrayList<Object> idParam = new ArrayList<>();
                 idParam.add("id1");
-                return new ArrayList[] {idParam};
+                return new ArrayList[]{idParam};
             }
         }, paramAppender);
 
-        Assert.assertEquals(Collections.singletonList("id1"), paramAppender);
+        Assertions.assertEquals(Collections.singletonList("id1"), paramAppender);
 
-        Assert.assertEquals("id = ?", whereCondition);
+        Assertions.assertEquals("id = ?", whereCondition);
+    }
+
+    /**
+     * Update recognizer test 3.
+     */
+    @Test
+    public void updateRecognizerTest_3() {
+
+        String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in (?, ?)";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
+
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> id1Param = new ArrayList<>();
+                id1Param.add("id1");
+                ArrayList<Object> id2Param = new ArrayList<>();
+                id2Param.add("id2");
+                return new ArrayList[]{id1Param, id2Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Arrays.asList("id1", "id2"), paramAppender);
+
+        Assertions.assertEquals("id IN (?, ?)", whereCondition);
+    }
+
+    /**
+     * Update recognizer test 4.
+     */
+    @Test
+    public void updateRecognizerTest_4() {
+
+        String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in (?, ?) and name1 = ?";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
+
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> id1Param = new ArrayList<>();
+                id1Param.add("id1");
+                ArrayList<Object> id2Param = new ArrayList<>();
+                id2Param.add("id2");
+                ArrayList<Object> name1Param = new ArrayList<>();
+                name1Param.add("name");
+                return new ArrayList[]{id1Param, id2Param, name1Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Arrays.asList("id1", "id2", "name"), paramAppender);
+
+        Assertions.assertEquals("id IN (?, ?)\nAND name1 = ?", whereCondition);
+    }
+
+    /**
+     * Update recognizer test 5.
+     */
+    @Test
+    public void updateRecognizerTest_5() {
+
+        String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id between ? and ?";
+
+        SQLStatement statement = getSQLStatement(sql);
+
+        MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
+
+        Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
+        Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
+        Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
+        Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
+        Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
+
+        ArrayList<Object> paramAppender = new ArrayList<>();
+        String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
+            @Override
+            public ArrayList<Object>[] getParameters() {
+                ArrayList<Object> id1Param = new ArrayList<>();
+                id1Param.add("id1");
+                ArrayList<Object> id2Param = new ArrayList<>();
+                id2Param.add("id2");
+                return new ArrayList[]{id1Param, id2Param};
+            }
+        }, paramAppender);
+
+        Assertions.assertEquals(Arrays.asList("id1", "id2"), paramAppender);
+        Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
     }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java
index 3353cfd26256530876aa54b0a6d6fab9e281eb2d..f51417a555ddd3b38097b97976ccbb85d1aca6e3 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/sql/struct/TableMetaTest.java
@@ -34,8 +34,8 @@ import com.alibaba.druid.pool.DruidDataSource;
 import com.alibaba.druid.util.jdbc.ResultSetMetaDataBase;
 import io.seata.rm.datasource.DataSourceProxy;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The table meta fetch test.
@@ -92,56 +92,56 @@ public class TableMetaTest {
 
         TableMeta tableMeta = TableMetaCache.getTableMeta(proxy, "t1");
 
-        Assert.assertEquals("t1", tableMeta.getTableName());
-        Assert.assertEquals("id", tableMeta.getPkName());
+        Assertions.assertEquals("t1", tableMeta.getTableName());
+        Assertions.assertEquals("id", tableMeta.getPkName());
 
-        Assert.assertEquals("id", tableMeta.getColumnMeta("id").getColumnName());
-        Assert.assertEquals("id", tableMeta.getAutoIncreaseColumn().getColumnName());
-        Assert.assertEquals(1, tableMeta.getPrimaryKeyMap().size());
-        Assert.assertEquals(Collections.singletonList("id"), tableMeta.getPrimaryKeyOnlyName());
+        Assertions.assertEquals("id", tableMeta.getColumnMeta("id").getColumnName());
+        Assertions.assertEquals("id", tableMeta.getAutoIncreaseColumn().getColumnName());
+        Assertions.assertEquals(1, tableMeta.getPrimaryKeyMap().size());
+        Assertions.assertEquals(Collections.singletonList("id"), tableMeta.getPrimaryKeyOnlyName());
 
-        Assert.assertEquals(4, tableMeta.getAllColumns().size());
+        Assertions.assertEquals(4, tableMeta.getAllColumns().size());
 
         assertColumnMetaEquals(columnMetas[0], tableMeta.getAllColumns().get("id"));
         assertColumnMetaEquals(columnMetas[1], tableMeta.getAllColumns().get("name1"));
         assertColumnMetaEquals(columnMetas[2], tableMeta.getAllColumns().get("name2"));
         assertColumnMetaEquals(columnMetas[3], tableMeta.getAllColumns().get("name3"));
 
-        Assert.assertEquals(2, tableMeta.getAllIndexes().size());
+        Assertions.assertEquals(2, tableMeta.getAllIndexes().size());
 
         assertIndexMetaEquals(indexMetas[0], tableMeta.getAllIndexes().get("PRIMARY"));
-        Assert.assertEquals(IndexType.PRIMARY, tableMeta.getAllIndexes().get("PRIMARY").getIndextype());
+        Assertions.assertEquals(IndexType.PRIMARY, tableMeta.getAllIndexes().get("PRIMARY").getIndextype());
         assertIndexMetaEquals(indexMetas[1], tableMeta.getAllIndexes().get("name1"));
-        Assert.assertEquals(IndexType.Unique, tableMeta.getAllIndexes().get("name1").getIndextype());
+        Assertions.assertEquals(IndexType.Unique, tableMeta.getAllIndexes().get("name1").getIndextype());
 
     }
 
     private void assertColumnMetaEquals(Object[] expected, ColumnMeta actual) {
-        Assert.assertEquals(expected[0], actual.getTableCat());
-        Assert.assertEquals(expected[3], actual.getColumnName());
-        Assert.assertEquals(expected[4], actual.getDataType());
-        Assert.assertEquals(expected[5], actual.getDataTypeName());
-        Assert.assertEquals(expected[6], actual.getColumnSize());
-        Assert.assertEquals(expected[7], actual.getDecimalDigits());
-        Assert.assertEquals(expected[8], actual.getNumPrecRadix());
-        Assert.assertEquals(expected[9], actual.getNullAble());
-        Assert.assertEquals(expected[10], actual.getRemarks());
-        Assert.assertEquals(expected[11], actual.getColumnDef());
-        Assert.assertEquals(expected[12], actual.getSqlDataType());
-        Assert.assertEquals(expected[13], actual.getSqlDatetimeSub());
-        Assert.assertEquals(expected[14], actual.getCharOctetLength());
-        Assert.assertEquals(expected[15], actual.getOrdinalPosition());
-        Assert.assertEquals(expected[16], actual.getIsNullAble());
-        Assert.assertEquals(expected[17], actual.getIsAutoincrement());
+        Assertions.assertEquals(expected[0], actual.getTableCat());
+        Assertions.assertEquals(expected[3], actual.getColumnName());
+        Assertions.assertEquals(expected[4], actual.getDataType());
+        Assertions.assertEquals(expected[5], actual.getDataTypeName());
+        Assertions.assertEquals(expected[6], actual.getColumnSize());
+        Assertions.assertEquals(expected[7], actual.getDecimalDigits());
+        Assertions.assertEquals(expected[8], actual.getNumPrecRadix());
+        Assertions.assertEquals(expected[9], actual.getNullAble());
+        Assertions.assertEquals(expected[10], actual.getRemarks());
+        Assertions.assertEquals(expected[11], actual.getColumnDef());
+        Assertions.assertEquals(expected[12], actual.getSqlDataType());
+        Assertions.assertEquals(expected[13], actual.getSqlDatetimeSub());
+        Assertions.assertEquals(expected[14], actual.getCharOctetLength());
+        Assertions.assertEquals(expected[15], actual.getOrdinalPosition());
+        Assertions.assertEquals(expected[16], actual.getIsNullAble());
+        Assertions.assertEquals(expected[17], actual.getIsAutoincrement());
     }
 
     private void assertIndexMetaEquals(Object[] expected, IndexMeta actual) {
-        Assert.assertEquals(expected[0], actual.getIndexName());
-        Assert.assertEquals(expected[3], actual.getIndexQualifier());
-        Assert.assertEquals(expected[4], (int)actual.getType());
-        Assert.assertEquals(expected[5], actual.getOrdinalPosition());
-        Assert.assertEquals(expected[6], actual.getAscOrDesc());
-        Assert.assertEquals(expected[7], actual.getCardinality());
+        Assertions.assertEquals(expected[0], actual.getIndexName());
+        Assertions.assertEquals(expected[3], actual.getIndexQualifier());
+        Assertions.assertEquals(expected[4], (int)actual.getType());
+        Assertions.assertEquals(expected[5], actual.getOrdinalPosition());
+        Assertions.assertEquals(expected[6], actual.getAscOrDesc());
+        Assertions.assertEquals(expected[7], actual.getCardinality());
     }
 
     private class MockDriver extends com.alibaba.druid.mock.MockDriver {
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseExecutorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f1848408774e130bea2641f4ac2b23708745c2b
--- /dev/null
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BaseExecutorTest.java
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.rm.datasource.undo;
+
+import io.seata.rm.datasource.sql.struct.Field;
+import io.seata.rm.datasource.sql.struct.KeyType;
+import io.seata.rm.datasource.sql.struct.Row;
+
+/**
+ * @author Geng Zhang
+ */
+public class BaseExecutorTest {
+
+    protected static Field addField(Row row, String name, int type, Object value) {
+        Field field = new Field(name, type, value);
+        if (name.equalsIgnoreCase("id")) {
+            field.setKeyType(KeyType.PrimaryKey);
+        }
+        row.add(field);
+        return field;
+    }
+}
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java
index 3a26d32559e1c51f4076185554039ebc583a1a80..3cc5dcc74f9c55f11a75d36510708b29baf0ec4f 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/BranchUndoLogTest.java
@@ -24,8 +24,8 @@ import io.seata.rm.datasource.sql.struct.Row;
 import io.seata.rm.datasource.sql.struct.TableMeta;
 import io.seata.rm.datasource.sql.struct.TableRecords;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Branch undo log test.
@@ -72,7 +72,7 @@ public class BranchUndoLogTest {
         System.out.println(encodeString);
 
         BranchUndoLog decodeObj = UndoLogParserFactory.getInstance().decode(encodeString);
-        Assert.assertEquals(decodeObj.getBranchId(), branchUndoLog.getBranchId());
+        Assertions.assertEquals(decodeObj.getBranchId(), branchUndoLog.getBranchId());
 
     }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java
index f026b4677587054cf1e11ed5a8d19848d6b0beaf..eb7a0324bb26c6ddf99164c6fd544ea82d4ca17a 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoExecutorTest.java
@@ -58,7 +58,7 @@ import io.seata.rm.datasource.sql.struct.Row;
 import io.seata.rm.datasource.sql.struct.TableMeta;
 import io.seata.rm.datasource.sql.struct.TableRecords;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Undo executor test.
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java
index 8b06aaa158f82b00e0dc695f9a695b22033b4047..dcc8f5d4ddc3606f75d988fc9626f2aab8305ab9 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/UndoLogManagerTest.java
@@ -15,7 +15,7 @@
  */
 package io.seata.rm.datasource.undo;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd0580b23e6af517f0775cdd23cfb8ca512d4f76
--- /dev/null
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoDeleteExecutorTest.java
@@ -0,0 +1,95 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.rm.datasource.undo.mysql;
+
+import io.seata.rm.datasource.sql.SQLType;
+import io.seata.rm.datasource.sql.struct.Row;
+import io.seata.rm.datasource.sql.struct.TableMeta;
+import io.seata.rm.datasource.sql.struct.TableRecords;
+import io.seata.rm.datasource.undo.BaseExecutorTest;
+import io.seata.rm.datasource.undo.SQLUndoLog;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Geng Zhang
+ */
+public class MySQLUndoDeleteExecutorTest extends BaseExecutorTest {
+
+    private static MySQLUndoDeleteExecutor executor;
+
+    @BeforeAll
+    public static void init(){
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(tableMeta.getPkName()).thenReturn("id");
+        Mockito.when(tableMeta.getTableName()).thenReturn("table_name");
+
+        TableRecords beforeImage = new TableRecords();
+        beforeImage.setTableName("table_name");
+        beforeImage.setTableMeta(tableMeta);
+        List<Row> beforeRows = new ArrayList<>();
+        Row row0 = new Row();
+        addField(row0, "id", 1, "12345");
+        addField(row0, "age", 1, "1");
+        beforeRows.add(row0);
+        Row row1 = new Row();
+        addField(row1, "id", 1, "12346");
+        addField(row1, "age", 1, "1");
+        beforeRows.add(row1);
+        beforeImage.setRows(beforeRows);
+
+        TableRecords afterImage = new TableRecords();
+        afterImage.setTableName("table_name");
+        afterImage.setTableMeta(tableMeta);
+        List<Row> afterRows = new ArrayList<>();
+        Row row2 = new Row();
+        addField(row2, "id", 1, "12345");
+        addField(row2, "age", 1, "2");
+        afterRows.add(row2);
+        Row row3 = new Row();
+        addField(row3, "id", 1, "12346");
+        addField(row3, "age", 1, "2");
+        afterRows.add(row3);
+        afterImage.setRows(afterRows);
+
+        SQLUndoLog sqlUndoLog = new SQLUndoLog();
+        sqlUndoLog.setSqlType(SQLType.UPDATE);
+        sqlUndoLog.setTableMeta(tableMeta);
+        sqlUndoLog.setTableName("table_name");
+        sqlUndoLog.setBeforeImage(beforeImage);
+        sqlUndoLog.setAfterImage(afterImage);
+
+        executor = new MySQLUndoDeleteExecutor(sqlUndoLog);
+    }
+
+    @Test
+    public void buildUndoSQL() {
+        String sql = executor.buildUndoSQL().toLowerCase();
+        Assertions.assertNotNull(sql);
+        Assertions.assertTrue(sql.contains("insert"));
+        Assertions.assertTrue(sql.contains("id"));
+    }
+    
+    @Test
+    public void getUndoRows() {
+        Assertions.assertEquals(executor.getUndoRows(), executor.getSqlUndoLog().getBeforeImage());
+    }
+}
\ No newline at end of file
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea24f713b031b3bfde0e565a667ccec07b12b1e0
--- /dev/null
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoInsertExecutorTest.java
@@ -0,0 +1,95 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.rm.datasource.undo.mysql;
+
+import io.seata.rm.datasource.sql.SQLType;
+import io.seata.rm.datasource.sql.struct.Row;
+import io.seata.rm.datasource.sql.struct.TableMeta;
+import io.seata.rm.datasource.sql.struct.TableRecords;
+import io.seata.rm.datasource.undo.BaseExecutorTest;
+import io.seata.rm.datasource.undo.SQLUndoLog;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Geng Zhang
+ */
+public class MySQLUndoInsertExecutorTest extends BaseExecutorTest {
+
+    private static MySQLUndoInsertExecutor executor;
+
+    @BeforeAll
+    public static void init(){
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(tableMeta.getPkName()).thenReturn("id");
+        Mockito.when(tableMeta.getTableName()).thenReturn("table_name");
+
+        TableRecords beforeImage = new TableRecords();
+        beforeImage.setTableName("table_name");
+        beforeImage.setTableMeta(tableMeta);
+        List<Row> beforeRows = new ArrayList<>();
+        Row row0 = new Row();
+        addField(row0, "id", 1, "12345");
+        addField(row0, "age", 1, "1");
+        beforeRows.add(row0);
+        Row row1 = new Row();
+        addField(row1, "id", 1, "12346");
+        addField(row1, "age", 1, "1");
+        beforeRows.add(row1);
+        beforeImage.setRows(beforeRows);
+
+        TableRecords afterImage = new TableRecords();
+        afterImage.setTableName("table_name");
+        afterImage.setTableMeta(tableMeta);
+        List<Row> afterRows = new ArrayList<>();
+        Row row2 = new Row();
+        addField(row2, "id", 1, "12345");
+        addField(row2, "age", 1, "2");
+        afterRows.add(row2);
+        Row row3 = new Row();
+        addField(row3, "id", 1, "12346");
+        addField(row3, "age", 1, "2");
+        afterRows.add(row3);
+        afterImage.setRows(afterRows);
+
+        SQLUndoLog sqlUndoLog = new SQLUndoLog();
+        sqlUndoLog.setSqlType(SQLType.UPDATE);
+        sqlUndoLog.setTableMeta(tableMeta);
+        sqlUndoLog.setTableName("table_name");
+        sqlUndoLog.setBeforeImage(beforeImage);
+        sqlUndoLog.setAfterImage(afterImage);
+
+        executor = new MySQLUndoInsertExecutor(sqlUndoLog);
+    }
+
+    @Test
+    public void buildUndoSQL() {
+        String sql = executor.buildUndoSQL().toLowerCase();
+        Assertions.assertNotNull(sql);
+        Assertions.assertTrue(sql.contains("delete"));
+        Assertions.assertTrue(sql.contains("id"));
+    }
+
+    @Test
+    public void getUndoRows() {
+        Assertions.assertEquals(executor.getUndoRows(), executor.getSqlUndoLog().getAfterImage());
+    }
+}
\ No newline at end of file
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1566e12eaa7c080b49eedbeb57269882417e4bb7
--- /dev/null
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/MySQLUndoUpdateExecutorTest.java
@@ -0,0 +1,97 @@
+/*
+ *  Copyright 1999-2019 Seata.io Group.
+ *
+ *  Licensed 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 io.seata.rm.datasource.undo.mysql;
+
+import io.seata.rm.datasource.sql.SQLType;
+import io.seata.rm.datasource.sql.struct.Row;
+import io.seata.rm.datasource.sql.struct.TableMeta;
+import io.seata.rm.datasource.sql.struct.TableRecords;
+import io.seata.rm.datasource.undo.BaseExecutorTest;
+import io.seata.rm.datasource.undo.SQLUndoLog;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Geng Zhang
+ */
+public class MySQLUndoUpdateExecutorTest extends BaseExecutorTest {
+
+    private static MySQLUndoUpdateExecutor executor;
+    
+    @BeforeAll
+    public static void init(){
+        TableMeta tableMeta = Mockito.mock(TableMeta.class);
+        Mockito.when(tableMeta.getPkName()).thenReturn("id");
+        Mockito.when(tableMeta.getTableName()).thenReturn("table_name");
+
+        TableRecords beforeImage = new TableRecords();
+        beforeImage.setTableName("table_name");
+        beforeImage.setTableMeta(tableMeta);
+        List<Row> beforeRows = new ArrayList<>();
+        Row row0 = new Row();
+        addField(row0, "id", 1, "12345");
+        addField(row0, "age", 1, "1");
+        beforeRows.add(row0);
+        Row row1 = new Row();
+        addField(row1, "id", 1, "12346");
+        addField(row1, "age", 1, "1");
+        beforeRows.add(row1);
+        beforeImage.setRows(beforeRows);
+
+        TableRecords afterImage = new TableRecords();
+        afterImage.setTableName("table_name");
+        afterImage.setTableMeta(tableMeta);
+        List<Row> afterRows = new ArrayList<>();
+        Row row2 = new Row();
+        addField(row2, "id", 1, "12345");
+        addField(row2, "age", 1, "2");
+        afterRows.add(row2);
+        Row row3 = new Row();
+        addField(row3, "id", 1, "12346");
+        addField(row3, "age", 1, "2");
+        afterRows.add(row3);
+        afterImage.setRows(afterRows);
+
+        SQLUndoLog sqlUndoLog = new SQLUndoLog();
+        sqlUndoLog.setSqlType(SQLType.UPDATE);
+        sqlUndoLog.setTableMeta(tableMeta);
+        sqlUndoLog.setTableName("table_name");
+        sqlUndoLog.setBeforeImage(beforeImage);
+        sqlUndoLog.setAfterImage(afterImage);
+
+        executor = new MySQLUndoUpdateExecutor(sqlUndoLog);
+    }
+
+    @Test
+    public void buildUndoSQL() {
+        String sql = executor.buildUndoSQL().toLowerCase();
+        Assertions.assertNotNull(sql);
+        Assertions.assertTrue(sql.contains("update"));
+        Assertions.assertTrue(sql.contains("id"));
+        Assertions.assertTrue(sql.contains("age"));
+    }
+
+    @Test
+    public void getUndoRows() {
+        Assertions.assertEquals(executor.getUndoRows(), executor.getSqlUndoLog().getBeforeImage());
+    }
+
+}
\ No newline at end of file
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java
index df410d62c5afe8df2adbecc7e83acc9f02d7c03d..879b77a88cdded38da225d3bf4418cd6c4042b5f 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/undo/mysql/keyword/MySQLKeywordCheckerTest.java
@@ -32,8 +32,8 @@ import io.seata.rm.datasource.undo.mysql.MySQLUndoInsertExecutor;
 import io.seata.rm.datasource.undo.mysql.MySQLUndoUpdateExecutor;
 
 import io.seata.rm.datasource.undo.UndoExecutorTest;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type My sql keyword checker test.
@@ -49,7 +49,7 @@ public class MySQLKeywordCheckerTest {
     @Test
     public void testCheck() {
         KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL);
-        Assert.assertTrue(keywordChecker.check("desc"));
+        Assertions.assertTrue(keywordChecker.check("desc"));
 
     }
 
@@ -59,7 +59,7 @@ public class MySQLKeywordCheckerTest {
     @Test
     public void testCheckAndReplace() {
         KeywordChecker keywordChecker = KeywordCheckerFactory.getKeywordChecker(JdbcConstants.MYSQL);
-        Assert.assertEquals("`desc`", keywordChecker.checkAndReplace("desc"));
+        Assertions.assertEquals("`desc`", keywordChecker.checkAndReplace("desc"));
 
     }
 
@@ -72,13 +72,13 @@ public class MySQLKeywordCheckerTest {
         sqlUndoLog.setTableName("lock");
         sqlUndoLog.setSqlType(SQLType.UPDATE);
 
-        TableRecords beforeImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "id"));
+        TableRecords beforeImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "key"));
 
         Row beforeRow = new Row();
 
         Field pkField = new Field();
         pkField.setKeyType(KeyType.PrimaryKey);
-        pkField.setName("id");
+        pkField.setName("key");
         pkField.setType(Types.INTEGER);
         pkField.setValue(213);
         beforeRow.add(pkField);
@@ -89,12 +89,6 @@ public class MySQLKeywordCheckerTest {
         name.setValue("SEATA");
         beforeRow.add(name);
 
-        Field nameOrder = new Field();
-        nameOrder.setName("order");
-        nameOrder.setType(Types.VARCHAR);
-        nameOrder.setValue("2");
-        beforeRow.add(nameOrder);
-
         Field since = new Field();
         since.setName("since");
         since.setType(Types.VARCHAR);
@@ -103,19 +97,19 @@ public class MySQLKeywordCheckerTest {
 
         beforeImage.add(beforeRow);
 
-        TableRecords afterImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "id"));
+        TableRecords afterImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "key"));
 
         Row afterRow = new Row();
 
         Field pkField1 = new Field();
         pkField1.setKeyType(KeyType.PrimaryKey);
-        pkField1.setName("id");
+        pkField1.setName("key");
         pkField1.setType(Types.INTEGER);
-        pkField1.setValue(213);
+        pkField1.setValue(214);
         afterRow.add(pkField1);
 
         Field name1 = new Field();
-        name1.setName("name");
+        name1.setName("desc");
         name1.setType(Types.VARCHAR);
         name1.setValue("GTS");
         afterRow.add(name1);
@@ -133,7 +127,7 @@ public class MySQLKeywordCheckerTest {
 
         MySQLUndoUpdateExecutorExtension mySQLUndoUpdateExecutor = new MySQLUndoUpdateExecutorExtension(sqlUndoLog);
 
-        Assert.assertEquals("UPDATE `lock` SET `desc` = ?, `order` = ?, since = ? WHERE id = ?",
+        Assertions.assertEquals("UPDATE `lock` SET `desc` = ?, since = ? WHERE `key` = ?",
             mySQLUndoUpdateExecutor.getSql());
 
     }
@@ -167,15 +161,15 @@ public class MySQLKeywordCheckerTest {
         sqlUndoLog.setTableName("lock");
         sqlUndoLog.setSqlType(SQLType.INSERT);
 
-        TableRecords beforeImage = TableRecords.empty(new UndoExecutorTest.MockTableMeta("product", "id"));
+        TableRecords beforeImage = TableRecords.empty(new UndoExecutorTest.MockTableMeta("product", "key"));
 
-        TableRecords afterImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "id"));
+        TableRecords afterImage = new TableRecords(new UndoExecutorTest.MockTableMeta("product", "key"));
 
         Row afterRow1 = new Row();
 
         Field pkField = new Field();
         pkField.setKeyType(KeyType.PrimaryKey);
-        pkField.setName("id");
+        pkField.setName("key");
         pkField.setType(Types.INTEGER);
         pkField.setValue(213);
         afterRow1.add(pkField);
@@ -187,7 +181,7 @@ public class MySQLKeywordCheckerTest {
         afterRow1.add(name);
 
         Field since = new Field();
-        since.setName("order");
+        since.setName("since");
         since.setType(Types.VARCHAR);
         since.setValue("2014");
         afterRow1.add(since);
@@ -196,13 +190,13 @@ public class MySQLKeywordCheckerTest {
 
         Field pkField1 = new Field();
         pkField1.setKeyType(KeyType.PrimaryKey);
-        pkField1.setName("id");
+        pkField1.setName("key");
         pkField1.setType(Types.INTEGER);
         pkField1.setValue(214);
         afterRow.add(pkField1);
 
         Field name1 = new Field();
-        name1.setName("name");
+        name1.setName("desc");
         name1.setType(Types.VARCHAR);
         name1.setValue("GTS");
         afterRow.add(name1);
@@ -221,7 +215,7 @@ public class MySQLKeywordCheckerTest {
 
         MySQLUndoInsertExecutorExtension mySQLUndoInsertExecutor = new MySQLUndoInsertExecutorExtension(sqlUndoLog);
 
-        Assert.assertEquals("DELETE FROM `lock` WHERE id = ?", mySQLUndoInsertExecutor.getSql());
+        Assertions.assertEquals("DELETE FROM `lock` WHERE `key` = ?", mySQLUndoInsertExecutor.getSql());
 
     }
 
@@ -262,7 +256,7 @@ public class MySQLKeywordCheckerTest {
 
         Field pkField = new Field();
         pkField.setKeyType(KeyType.PrimaryKey);
-        pkField.setName("id");
+        pkField.setName("key");
         pkField.setType(Types.INTEGER);
         pkField.setValue(213);
         afterRow1.add(pkField);
@@ -274,7 +268,7 @@ public class MySQLKeywordCheckerTest {
         afterRow1.add(name);
 
         Field since = new Field();
-        since.setName("order");
+        since.setName("since");
         since.setType(Types.VARCHAR);
         since.setValue("2014");
         afterRow1.add(since);
@@ -283,13 +277,13 @@ public class MySQLKeywordCheckerTest {
 
         Field pkField1 = new Field();
         pkField1.setKeyType(KeyType.PrimaryKey);
-        pkField1.setName("id");
+        pkField1.setName("key");
         pkField1.setType(Types.INTEGER);
         pkField1.setValue(214);
         afterRow.add(pkField1);
 
         Field name1 = new Field();
-        name1.setName("name");
+        name1.setName("desc");
         name1.setType(Types.VARCHAR);
         name1.setValue("GTS");
         afterRow.add(name1);
@@ -308,7 +302,7 @@ public class MySQLKeywordCheckerTest {
 
         MySQLUndoDeleteExecutorExtension mySQLUndoDeleteExecutor = new MySQLUndoDeleteExecutorExtension(sqlUndoLog);
 
-        Assert.assertEquals("INSERT INTO `lock`(`desc`, `order`, id) VALUES (?, ?, ?)",
+        Assertions.assertEquals("INSERT INTO `lock` (`desc`, since, `key`) VALUES (?, ?, ?)",
             mySQLUndoDeleteExecutor.getSql());
 
     }
diff --git a/rm/pom.xml b/rm/pom.xml
index 68de083aae804de7d39d94453c172d57ad472a42..7a602ed56df852d115ae96f17abfcb1f0fdb29e5 100644
--- a/rm/pom.xml
+++ b/rm/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -31,22 +31,12 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring</artifactId>
-            <scope>provided</scope>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>cglib</groupId>
             <artifactId>cglib</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
 
diff --git a/rm/src/main/java/io/seata/rm/AbstractRMHandler.java b/rm/src/main/java/io/seata/rm/AbstractRMHandler.java
index fa7f929f53b85e1aef4727a803ffba594df35c4e..bff918849ac09bf00a2ba331f421a9595a064efb 100644
--- a/rm/src/main/java/io/seata/rm/AbstractRMHandler.java
+++ b/rm/src/main/java/io/seata/rm/AbstractRMHandler.java
@@ -31,7 +31,6 @@ import io.seata.core.protocol.transaction.BranchRollbackResponse;
 import io.seata.core.protocol.transaction.RMInboundHandler;
 import io.seata.core.rpc.RpcContext;
 import io.seata.core.rpc.TransactionMessageHandler;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,7 +47,7 @@ public abstract class AbstractRMHandler extends AbstractExceptionHandler
     @Override
     public BranchCommitResponse handle(BranchCommitRequest request) {
         BranchCommitResponse response = new BranchCommitResponse();
-        exceptionHandleTemplate(new AbstractExceptionHandler.Callback<BranchCommitRequest, BranchCommitResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<BranchCommitRequest, BranchCommitResponse>() {
             @Override
             public void execute(BranchCommitRequest request, BranchCommitResponse response)
                 throws TransactionException {
@@ -61,7 +60,7 @@ public abstract class AbstractRMHandler extends AbstractExceptionHandler
     @Override
     public BranchRollbackResponse handle(BranchRollbackRequest request) {
         BranchRollbackResponse response = new BranchRollbackResponse();
-        exceptionHandleTemplate(new Callback<BranchRollbackRequest, BranchRollbackResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<BranchRollbackRequest, BranchRollbackResponse>() {
             @Override
             public void execute(BranchRollbackRequest request, BranchRollbackResponse response)
                 throws TransactionException {
diff --git a/server/pom.xml b/server/pom.xml
index b7420e4271f329e33ea5642985f64afea12d226c..55290bec0ee9cdfd89784ff3d71097cf4bbac865 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -28,31 +28,23 @@
     <name>seata-server ${project.version}</name>
 
     <dependencies>
+
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-core</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-config-all</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-discovery-all</artifactId>
+            <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>commons-lang</groupId>
-            <artifactId>commons-lang</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <scope>test</scope>
-        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java b/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
index 7a1d972292817be2e9cfebf9b983b05cf41a5076..d6655196eeee371631db759df2e063a174c861c1 100644
--- a/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
+++ b/server/src/main/java/io/seata/server/AbstractTCInboundHandler.java
@@ -15,8 +15,10 @@
  */
 package io.seata.server;
 
+import io.seata.common.XID;
 import io.seata.core.exception.AbstractExceptionHandler;
 import io.seata.core.exception.TransactionException;
+import io.seata.core.model.GlobalStatus;
 import io.seata.core.protocol.transaction.BranchRegisterRequest;
 import io.seata.core.protocol.transaction.BranchRegisterResponse;
 import io.seata.core.protocol.transaction.BranchReportRequest;
@@ -33,6 +35,8 @@ import io.seata.core.protocol.transaction.GlobalStatusRequest;
 import io.seata.core.protocol.transaction.GlobalStatusResponse;
 import io.seata.core.protocol.transaction.TCInboundHandler;
 import io.seata.core.rpc.RpcContext;
+import io.seata.server.session.GlobalSession;
+import io.seata.server.session.SessionHolder;
 
 /**
  * The type Abstract tc inbound handler.
@@ -44,7 +48,7 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
     @Override
     public GlobalBeginResponse handle(GlobalBeginRequest request, final RpcContext rpcContext) {
         GlobalBeginResponse response = new GlobalBeginResponse();
-        exceptionHandleTemplate(new Callback<GlobalBeginRequest, GlobalBeginResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<GlobalBeginRequest, GlobalBeginResponse>() {
             @Override
             public void execute(GlobalBeginRequest request, GlobalBeginResponse response) throws TransactionException {
                 doGlobalBegin(request, response, rpcContext);
@@ -62,12 +66,12 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response,
-                                          RpcContext rpcContext) throws TransactionException;
+        RpcContext rpcContext) throws TransactionException;
 
     @Override
     public GlobalCommitResponse handle(GlobalCommitRequest request, final RpcContext rpcContext) {
         GlobalCommitResponse response = new GlobalCommitResponse();
-        exceptionHandleTemplate(new Callback<GlobalCommitRequest, GlobalCommitResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<GlobalCommitRequest, GlobalCommitResponse>() {
             @Override
             public void execute(GlobalCommitRequest request, GlobalCommitResponse response)
                 throws TransactionException {
@@ -86,17 +90,42 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response,
-                                           RpcContext rpcContext) throws TransactionException;
+        RpcContext rpcContext) throws TransactionException;
 
     @Override
     public GlobalRollbackResponse handle(GlobalRollbackRequest request, final RpcContext rpcContext) {
         GlobalRollbackResponse response = new GlobalRollbackResponse();
-        exceptionHandleTemplate(new Callback<GlobalRollbackRequest, GlobalRollbackResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<GlobalRollbackRequest, GlobalRollbackResponse>() {
             @Override
             public void execute(GlobalRollbackRequest request, GlobalRollbackResponse response)
                 throws TransactionException {
                 doGlobalRollback(request, response, rpcContext);
             }
+
+            @Override
+            public void onTransactionException(GlobalRollbackRequest request, GlobalRollbackResponse response,
+                TransactionException tex) {
+                super.onTransactionException(request, response, tex);
+                GlobalSession globalSession = SessionHolder.findGlobalSession(
+                    XID.getTransactionId(request.getXid()));
+                if (globalSession != null) {
+                    response.setGlobalStatus(globalSession.getStatus());
+                } else {
+                    response.setGlobalStatus(GlobalStatus.Finished);
+                }
+            }
+
+            @Override
+            public void onException(GlobalRollbackRequest request, GlobalRollbackResponse response, Exception rex) {
+                super.onException(request, response, rex);
+                GlobalSession globalSession = SessionHolder.findGlobalSession(
+                    XID.getTransactionId(request.getXid()));
+                if (globalSession != null) {
+                    response.setGlobalStatus(globalSession.getStatus());
+                } else {
+                    response.setGlobalStatus(GlobalStatus.Finished);
+                }
+            }
         }, request, response);
         return response;
     }
@@ -110,12 +139,12 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response,
-                                             RpcContext rpcContext) throws TransactionException;
+        RpcContext rpcContext) throws TransactionException;
 
     @Override
     public BranchRegisterResponse handle(BranchRegisterRequest request, final RpcContext rpcContext) {
         BranchRegisterResponse response = new BranchRegisterResponse();
-        exceptionHandleTemplate(new Callback<BranchRegisterRequest, BranchRegisterResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<BranchRegisterRequest, BranchRegisterResponse>() {
             @Override
             public void execute(BranchRegisterRequest request, BranchRegisterResponse response)
                 throws TransactionException {
@@ -134,12 +163,12 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response,
-                                             RpcContext rpcContext) throws TransactionException;
+        RpcContext rpcContext) throws TransactionException;
 
     @Override
     public BranchReportResponse handle(BranchReportRequest request, final RpcContext rpcContext) {
         BranchReportResponse response = new BranchReportResponse();
-        exceptionHandleTemplate(new Callback<BranchReportRequest, BranchReportResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<BranchReportRequest, BranchReportResponse>() {
             @Override
             public void execute(BranchReportRequest request, BranchReportResponse response)
                 throws TransactionException {
@@ -157,13 +186,13 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doBranchReport(BranchReportRequest request, BranchReportResponse response,
-                                           RpcContext rpcContext)
+        RpcContext rpcContext)
         throws TransactionException;
 
     @Override
     public GlobalLockQueryResponse handle(GlobalLockQueryRequest request, final RpcContext rpcContext) {
         GlobalLockQueryResponse response = new GlobalLockQueryResponse();
-        exceptionHandleTemplate(new Callback<GlobalLockQueryRequest, GlobalLockQueryResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<GlobalLockQueryRequest, GlobalLockQueryResponse>() {
             @Override
             public void execute(GlobalLockQueryRequest request, GlobalLockQueryResponse response)
                 throws TransactionException {
@@ -182,12 +211,12 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doLockCheck(GlobalLockQueryRequest request, GlobalLockQueryResponse response,
-                                        RpcContext rpcContext) throws TransactionException;
+        RpcContext rpcContext) throws TransactionException;
 
     @Override
     public GlobalStatusResponse handle(GlobalStatusRequest request, final RpcContext rpcContext) {
         GlobalStatusResponse response = new GlobalStatusResponse();
-        exceptionHandleTemplate(new Callback<GlobalStatusRequest, GlobalStatusResponse>() {
+        exceptionHandleTemplate(new AbstractCallback<GlobalStatusRequest, GlobalStatusResponse>() {
             @Override
             public void execute(GlobalStatusRequest request, GlobalStatusResponse response)
                 throws TransactionException {
@@ -206,6 +235,6 @@ public abstract class AbstractTCInboundHandler extends AbstractExceptionHandler
      * @throws TransactionException the transaction exception
      */
     protected abstract void doGlobalStatus(GlobalStatusRequest request, GlobalStatusResponse response,
-                                           RpcContext rpcContext) throws TransactionException;
+        RpcContext rpcContext) throws TransactionException;
 
 }
diff --git a/server/src/main/java/io/seata/server/Server.java b/server/src/main/java/io/seata/server/Server.java
index a636e84d3487781d51ee6c6162b1016ad916ec28..92273a3e68fed718f276b95df19220e88994da68 100644
--- a/server/src/main/java/io/seata/server/Server.java
+++ b/server/src/main/java/io/seata/server/Server.java
@@ -71,6 +71,8 @@ public class Server {
         if (args.length > 1) {
             storeMode = args[1];
         }
+
+        UUIDGenerator.init(1);
         SessionHolder.init(storeMode);
 
         DefaultCoordinator coordinator = new DefaultCoordinator(rpcServer);
@@ -79,8 +81,6 @@ public class Server {
         // register ShutdownHook
         ShutdownHook.getInstance().addDisposable(coordinator);
 
-        UUIDGenerator.init(1);
-
         if (args.length > 2) {
             XID.setIpAddress(args[2]);
         } else {
diff --git a/server/src/main/java/io/seata/server/UUIDGenerator.java b/server/src/main/java/io/seata/server/UUIDGenerator.java
index becbe0e1f4e078dc700891268fd13fd82b4b82c5..efc55e555d30683dbd8c8f415709fe910863adaa 100644
--- a/server/src/main/java/io/seata/server/UUIDGenerator.java
+++ b/server/src/main/java/io/seata/server/UUIDGenerator.java
@@ -52,6 +52,27 @@ public class UUIDGenerator {
         return id;
     }
 
+    /**
+     * Gets current uuid.
+     *
+     * @return the current uuid
+     */
+    public static long getCurrentUUID() {
+        return UUID.get();
+    }
+
+    /**
+     * Sets uuid.
+     *
+     * @param expect the expect
+     * @param update the update
+     * @return the uuid
+     */
+    public static boolean setUUID(long expect, long update) {
+        return UUID.compareAndSet(expect, update);
+
+    }
+
     /**
      * Init.
      *
diff --git a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
index d98388ea66b49cd4e26988e3dbccfca4ea47c35a..15063da2cb22238481f6596ce9a22523fe84d368 100644
--- a/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
+++ b/server/src/main/java/io/seata/server/coordinator/DefaultCoordinator.java
@@ -157,6 +157,9 @@ public class DefaultCoordinator extends AbstractTCInboundHandler
             request.setBranchType(branchType);
 
             GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+            if(globalSession == null){
+                return BranchStatus.PhaseTwo_Committed;
+            }
             BranchSession branchSession = globalSession.getBranch(branchId);
 
             BranchCommitResponse response = (BranchCommitResponse)messageSender.sendSyncRequest(resourceId,
@@ -183,6 +186,9 @@ public class DefaultCoordinator extends AbstractTCInboundHandler
             request.setBranchType(branchType);
 
             GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
+            if(globalSession == null){
+                return BranchStatus.PhaseTwo_Rollbacked;
+            }
             BranchSession branchSession = globalSession.getBranch(branchId);
 
             BranchRollbackResponse response = (BranchRollbackResponse)messageSender.sendSyncRequest(resourceId,
diff --git a/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java b/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
index 1807ff1ec3219b1323d2549605a166e2ed11b5bb..14a68549987fbf913437cdef1265b84d1239113c 100644
--- a/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
+++ b/server/src/main/java/io/seata/server/lock/DefaultLockManagerImpl.java
@@ -41,10 +41,12 @@ public class DefaultLockManagerImpl implements LockManager {
 
     private static final int BUCKET_PER_TABLE = 128;
 
-    private static final ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<Integer, Map<String,
-        Long>>>>
-        LOCK_MAP
-        = new ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<Integer, Map<String, Long>>>>();
+    private static final
+    ConcurrentHashMap<String/* resourceId */,
+        ConcurrentHashMap<String/* tableName */,
+            ConcurrentHashMap<Integer/* bucketId */,
+                Map<String/* pk */, Long/* transactionId */>>>>
+        LOCK_MAP = new ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentHashMap<Integer, Map<String, Long>>>>();
 
     @Override
     public boolean acquireLock(BranchSession branchSession) throws TransactionException {
diff --git a/server/src/main/java/io/seata/server/session/AbstractSessionManager.java b/server/src/main/java/io/seata/server/session/AbstractSessionManager.java
index f124b010254aaac27d1b96641498263ec86ee2bc..d58f8b71d5a55f17f5031bac96fd2f03f0727643 100644
--- a/server/src/main/java/io/seata/server/session/AbstractSessionManager.java
+++ b/server/src/main/java/io/seata/server/session/AbstractSessionManager.java
@@ -80,7 +80,7 @@ public abstract class AbstractSessionManager implements SessionManager, SessionL
 
 
     @Override
-    public GlobalSession findGlobalSession(Long transactionId) throws TransactionException {
+    public GlobalSession findGlobalSession(Long transactionId) {
         return sessionMap.get(transactionId);
     }
 
diff --git a/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java b/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java
index 1cf82df345a6264c38c56a55cf3ea0c06ee540d0..1684cccdface1af2f8aa7077c562b6837cba69c4 100644
--- a/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java
+++ b/server/src/main/java/io/seata/server/session/FileBasedSessionManager.java
@@ -26,6 +26,7 @@ import io.seata.common.exception.ShouldNeverHappenException;
 import io.seata.config.ConfigurationFactory;
 import io.seata.core.constants.ConfigurationKeys;
 import io.seata.core.model.GlobalStatus;
+import io.seata.server.UUIDGenerator;
 import io.seata.server.store.FileTransactionStoreManager;
 import io.seata.server.store.SessionStorable;
 import io.seata.server.store.TransactionStoreManager;
@@ -39,7 +40,7 @@ import io.seata.server.store.TransactionWriteStore;
 public class FileBasedSessionManager extends AbstractSessionManager implements Reloadable {
 
     private static final int READ_SIZE = ConfigurationFactory.getInstance().getInt(
-            ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, 100);
+        ConfigurationKeys.SERVICE_SESSION_RELOAD_READ_SIZE, 100);
 
     /**
      * Instantiates a new File based session manager.
@@ -122,13 +123,15 @@ public class FileBasedSessionManager extends AbstractSessionManager implements R
     }
 
     private void restore(List<TransactionWriteStore> stores, Map<Long, BranchSession> unhandledBranchSessions) {
+        long maxRecoverId = UUIDGenerator.getCurrentUUID();
         for (TransactionWriteStore store : stores) {
             TransactionStoreManager.LogOperation logOperation = store.getOperate();
             SessionStorable sessionStorable = store.getSessionRequest();
+            maxRecoverId = getMaxId(maxRecoverId, sessionStorable);
             switch (logOperation) {
                 case GLOBAL_ADD:
                 case GLOBAL_UPDATE: {
-                    GlobalSession globalSession = (GlobalSession) sessionStorable;
+                    GlobalSession globalSession = (GlobalSession)sessionStorable;
                     long tid = globalSession.getTransactionId();
                     GlobalSession foundGlobalSession = sessionMap.get(tid);
                     if (foundGlobalSession == null) {
@@ -139,7 +142,7 @@ public class FileBasedSessionManager extends AbstractSessionManager implements R
                     break;
                 }
                 case GLOBAL_REMOVE: {
-                    GlobalSession globalSession = (GlobalSession) sessionStorable;
+                    GlobalSession globalSession = (GlobalSession)sessionStorable;
                     long tid = globalSession.getTransactionId();
                     if (sessionMap.remove(tid) == null) {
                         if (LOGGER.isInfoEnabled()) {
@@ -150,7 +153,7 @@ public class FileBasedSessionManager extends AbstractSessionManager implements R
                 }
                 case BRANCH_ADD:
                 case BRANCH_UPDATE: {
-                    BranchSession branchSession = (BranchSession) sessionStorable;
+                    BranchSession branchSession = (BranchSession)sessionStorable;
                     long tid = branchSession.getTransactionId();
                     GlobalSession foundGlobalSession = sessionMap.get(tid);
                     if (foundGlobalSession == null) {
@@ -166,15 +169,15 @@ public class FileBasedSessionManager extends AbstractSessionManager implements R
                     break;
                 }
                 case BRANCH_REMOVE: {
-                    BranchSession branchSession = (BranchSession) sessionStorable;
+                    BranchSession branchSession = (BranchSession)sessionStorable;
                     long tid = branchSession.getTransactionId();
                     long bid = branchSession.getBranchId();
                     GlobalSession found = sessionMap.get(tid);
                     if (found == null) {
                         if (LOGGER.isInfoEnabled()) {
                             LOGGER.info(
-                                    "GlobalSession To Be Updated (Remove Branch) Does Not Exists [" + bid + "/" + tid
-                                            + "]");
+                                "GlobalSession To Be Updated (Remove Branch) Does Not Exists [" + bid + "/" + tid
+                                    + "]");
                         }
                     } else {
                         BranchSession theBranch = found.getBranch(bid);
@@ -194,9 +197,31 @@ public class FileBasedSessionManager extends AbstractSessionManager implements R
 
             }
         }
+        setMaxId(maxRecoverId);
 
     }
 
+    private long getMaxId(long maxRecoverId, SessionStorable sessionStorable) {
+        long currentId = 0;
+        if (sessionStorable instanceof GlobalSession) {
+            currentId = ((GlobalSession)sessionStorable).getTransactionId();
+        } else if (sessionStorable instanceof BranchSession) {
+            currentId = ((BranchSession)sessionStorable).getBranchId();
+        }
+
+        return maxRecoverId > currentId ? maxRecoverId : currentId;
+    }
+
+    private void setMaxId(long maxRecoverId) {
+        long currentId;
+        // will be recover multi-thread later
+        while ((currentId = UUIDGenerator.getCurrentUUID()) < maxRecoverId) {
+            if (UUIDGenerator.setUUID(currentId, maxRecoverId)) {
+                break;
+            }
+        }
+    }
+
     private void restore(TransactionWriteStore store) {
     }
 
diff --git a/server/src/main/java/io/seata/server/session/GlobalSession.java b/server/src/main/java/io/seata/server/session/GlobalSession.java
index 7b8d6520247978112a86a1665afa06fc186598ba..1c9f31d5bda543df6cf57fc452d9fda330d275e8 100644
--- a/server/src/main/java/io/seata/server/session/GlobalSession.java
+++ b/server/src/main/java/io/seata/server/session/GlobalSession.java
@@ -23,12 +23,15 @@ import io.seata.core.model.GlobalStatus;
 import io.seata.server.UUIDGenerator;
 import io.seata.server.store.SessionStorable;
 import io.seata.server.store.StoreConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * The type Global session.
@@ -37,10 +40,12 @@ import java.util.concurrent.locks.LockSupport;
  */
 public class GlobalSession implements SessionLifecycle, SessionStorable {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalSession.class);
+
     private static final int MAX_GLOBAL_SESSION_SIZE = StoreConfig.getMaxGlobalSessionSize();
 
     private static ThreadLocal<ByteBuffer> byteBufferThreadLocal = ThreadLocal.withInitial(() -> ByteBuffer.allocate(
-        MAX_GLOBAL_SESSION_SIZE));
+            MAX_GLOBAL_SESSION_SIZE));
 
     private long transactionId;
 
@@ -60,7 +65,7 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
 
     private ArrayList<BranchSession> branchSessions = new ArrayList<>();
 
-    private GlobalSessionSpinLock globalSessionSpinLock = new GlobalSessionSpinLock();
+    private GlobalSessionLock globalSessionLock = new GlobalSessionLock();
 
     /**
      * Add boolean.
@@ -474,11 +479,11 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
     }
 
     public void lock() throws TransactionException {
-        globalSessionSpinLock.lock();
+        globalSessionLock.lock();
     }
 
     public void unlock(){
-        globalSessionSpinLock.unlock();
+        globalSessionLock.unlock();
     }
 
     public void lockAndExcute(LockRunnable excuteRunnable) throws TransactionException{
@@ -498,47 +503,27 @@ public class GlobalSession implements SessionLifecycle, SessionStorable {
             this.unlock();
         }
     }
-    /**
-     * globalsession is low race conditions, so use spinlock
-     */
-    private class GlobalSessionSpinLock{
-        /**
-         * true: Can lock, false : in lock.
-         */
-        private AtomicBoolean globalSessionSpinLock = new AtomicBoolean(true);
 
-        private static final int GLOBAL_SESSOION_LOCK_TIME_OUT_MILLS = 2 * 1000;
+    private class GlobalSessionLock {
 
-        private static final int PARK_TIMES_BASE = 10;
+        private Lock globalSessionLock = new ReentrantLock();
 
-        private static final int PARK_TIMES_BASE_NANOS = 1 * 1000 * 1000;
+        private static final int GLOBAL_SESSOION_LOCK_TIME_OUT_MILLS = 2 * 1000;
 
         public void lock() throws TransactionException {
-            boolean flag;
-            int times = 0;
-            long beginTime = System.currentTimeMillis();
-            long restTime = GLOBAL_SESSOION_LOCK_TIME_OUT_MILLS ;
-            do {
-                restTime -= (System.currentTimeMillis() - beginTime);
-                if (restTime <= 0){
-                    throw new TransactionException(TransactionExceptionCode.FailedLockGlobalTranscation);
-                }
-                // Pause every PARK_TIMES_BASE times,yield the CPU
-                if (times % PARK_TIMES_BASE == 0){
-                    // Exponential Backoff
-                    long backOffTime =  PARK_TIMES_BASE_NANOS << (times/PARK_TIMES_BASE);
-                    long parkTime = backOffTime < restTime ? backOffTime : restTime;
-                    LockSupport.parkNanos(parkTime);
+             try {
+                if (globalSessionLock.tryLock(GLOBAL_SESSOION_LOCK_TIME_OUT_MILLS, TimeUnit.MILLISECONDS)){
+                    return;
                 }
-                flag = this.globalSessionSpinLock.compareAndSet(true, false);
-                times++;
+            } catch (InterruptedException e) {
+                 LOGGER.error("Interrupted error", e);
             }
-            while (!flag);
+            throw new TransactionException(TransactionExceptionCode.FailedLockGlobalTranscation);
         }
 
 
         public void unlock() {
-            this.globalSessionSpinLock.compareAndSet(false, true);
+            globalSessionLock.unlock();
         }
 
     }
diff --git a/server/src/main/java/io/seata/server/session/SessionCondition.java b/server/src/main/java/io/seata/server/session/SessionCondition.java
index 6d04dd3616d974d4a893012344e4f27ec72a82c2..4063d7aa3780e9070e0d758140cbd20578e0de2e 100644
--- a/server/src/main/java/io/seata/server/session/SessionCondition.java
+++ b/server/src/main/java/io/seata/server/session/SessionCondition.java
@@ -15,10 +15,6 @@
  */
 package io.seata.server.session;
 
-import io.seata.core.model.GlobalStatus;
-
-import java.util.Set;
-
 /**
  * The type Session condition.
  *
diff --git a/server/src/main/java/io/seata/server/session/SessionHolder.java b/server/src/main/java/io/seata/server/session/SessionHolder.java
index 151512ffbce804f06c26f401a8958366d04a6138..30f4b4d00b3ba3fc5cd47f98dd545b3fe705f95a 100644
--- a/server/src/main/java/io/seata/server/session/SessionHolder.java
+++ b/server/src/main/java/io/seata/server/session/SessionHolder.java
@@ -225,13 +225,12 @@ public class SessionHolder {
     }
 
     /**
-     * Find global session global session.
+     * Find global session.
      *
      * @param transactionId the transaction id
      * @return the global session
-     * @throws TransactionException the transaction exception
      */
-    public static GlobalSession findGlobalSession(Long transactionId) throws TransactionException {
+    public static GlobalSession findGlobalSession(Long transactionId) {
         return getRootSessionManager().findGlobalSession(transactionId);
     }
 
diff --git a/server/src/main/java/io/seata/server/session/SessionManager.java b/server/src/main/java/io/seata/server/session/SessionManager.java
index 621b2011681225e9331c688c263f766c069f7f73..2883d440482d97d1f295b6c0acc8e7f72059203d 100644
--- a/server/src/main/java/io/seata/server/session/SessionManager.java
+++ b/server/src/main/java/io/seata/server/session/SessionManager.java
@@ -45,7 +45,7 @@ public interface SessionManager extends SessionLifecycleListener, Disposable {
      * @return the global session
      * @throws TransactionException the transaction exception
      */
-    GlobalSession findGlobalSession(Long transactionId) throws TransactionException;
+    GlobalSession findGlobalSession(Long transactionId);
 
     /**
      * Update global session status.
diff --git a/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java b/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java
index 6f9f0b286d1f65b8b68fface177fee3f6f90b1d3..9b3a32229c57e031c6c7c7edb1b00954a70a2a89 100644
--- a/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java
+++ b/server/src/main/java/io/seata/server/store/FileTransactionStoreManager.java
@@ -407,9 +407,9 @@ public class FileTransactionStoreManager implements TransactionStoreManager {
     }
 
     private boolean writeDataFileByBuffer(ByteBuffer byteBuffer) {
+        byteBuffer.flip();
         for (int retry = 0; retry < MAX_WRITE_RETRY; retry++) {
             try {
-                byteBuffer.flip();
                 while (byteBuffer.hasRemaining()) {
                     currFileChannel.write(byteBuffer);
                 }
diff --git a/server/src/main/java/io/seata/server/store/StoreConfig.java b/server/src/main/java/io/seata/server/store/StoreConfig.java
index ec257d2992c0ae58468771824c6ec63f19e8592f..37e2b0f3b8025429d86bca501fdcaba99d50743d 100644
--- a/server/src/main/java/io/seata/server/store/StoreConfig.java
+++ b/server/src/main/java/io/seata/server/store/StoreConfig.java
@@ -19,7 +19,6 @@ import io.seata.config.Configuration;
 import io.seata.config.ConfigurationFactory;
 
 import static io.seata.core.constants.ConfigurationKeys.STORE_FILE_PREFIX;
-import static io.seata.core.constants.ConfigurationKeys.STORE_PREFIX;
 
 
 /**
@@ -52,6 +51,6 @@ public class StoreConfig {
     }
 
     public static FlushDiskMode getFlushDiskMode() {
-        return FlushDiskMode.findDiskMode(CONFIGURATION.getConfig(STORE_PREFIX + "flush-disk-mode"));
+        return FlushDiskMode.findDiskMode(CONFIGURATION.getConfig(STORE_FILE_PREFIX + "flush-disk-mode"));
     }
 }
\ No newline at end of file
diff --git a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java
index 665a81e66be8bf73e23a7a76c36f50ae2bba00fd..da7d44a4ad942c6802dc4140170f5acd27922752 100644
--- a/server/src/main/java/io/seata/server/store/TransactionStoreManager.java
+++ b/server/src/main/java/io/seata/server/store/TransactionStoreManager.java
@@ -107,29 +107,12 @@ public interface TransactionStoreManager {
          * @return the log operation by code
          */
         public static LogOperation getLogOperationByCode(byte code) {
-            LogOperation logOperation = null;
-            switch (code) {
-                case 1:
-                    logOperation = LogOperation.GLOBAL_ADD;
-                    break;
-                case 2:
-                    logOperation = LogOperation.GLOBAL_UPDATE;
-                    break;
-                case 3:
-                    logOperation = LogOperation.GLOBAL_REMOVE;
-                    break;
-                case 4:
-                    logOperation = LogOperation.BRANCH_ADD;
-                    break;
-                case 5:
-                    logOperation = LogOperation.BRANCH_UPDATE;
-                    break;
-                case 6:
-                    logOperation = LogOperation.BRANCH_REMOVE;
-                    break;
-                default:
+            for (LogOperation temp : values()) {
+                if (temp.getCode() == code) {
+                    return temp;
+                }
             }
-            return logOperation;
+            throw new IllegalArgumentException("Unknown LogOperation[" + code + "]");
         }
     }
 }
diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml
index 0f819b7618d81e3997148d390c11832c1acef8c5..62d9e1acd56c81223fc52e0328e430f78e223c6a 100644
--- a/server/src/main/resources/logback.xml
+++ b/server/src/main/resources/logback.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/server/src/main/resources/registry.conf b/server/src/main/resources/registry.conf
index 15677236a892397e6babed5c83f1263b842a56c2..1cddea7219444a8f50ee5bdc7f7170de40884356 100644
--- a/server/src/main/resources/registry.conf
+++ b/server/src/main/resources/registry.conf
@@ -45,7 +45,7 @@ registry {
 }
 
 config {
-  # file、nacos 、apollo、zk
+  # file、nacos 、apollo、zk、consul
   type = "file"
 
   nacos {
@@ -53,6 +53,9 @@ config {
     namespace = "public"
     cluster = "default"
   }
+  consul {
+    serverAddr = "127.0.0.1:8500"
+  }
   apollo {
     app.id = "seata-server"
     apollo.meta = "http://192.168.1.204:8801"
diff --git a/server/src/test/java/WriteStoreMultithreadTest.java b/server/src/test/java/WriteStoreMultithreadTest.java
index f782bfae1e3524aae0b3bf840c358d51f95a600e..94eb5c8877069c078feeecb49be2999ec73ce7ff 100644
--- a/server/src/test/java/WriteStoreMultithreadTest.java
+++ b/server/src/test/java/WriteStoreMultithreadTest.java
@@ -55,7 +55,7 @@ public class WriteStoreMultithreadTest {
                     }
 
                     @Override
-                    public GlobalSession findGlobalSession(Long transactionId) throws TransactionException {
+                    public GlobalSession findGlobalSession(Long transactionId) {
                         return null;
                     }
 
diff --git a/server/src/test/java/WriteStoreTest.java b/server/src/test/java/WriteStoreTest.java
index 50cfcc19443c898a2073e875ded8a3c6de139a1f..9f9964d1b868156b382d7dd3accf1f971e8b9d69 100644
--- a/server/src/test/java/WriteStoreTest.java
+++ b/server/src/test/java/WriteStoreTest.java
@@ -71,7 +71,7 @@ public class WriteStoreTest {
                 }
 
                 @Override
-                public GlobalSession findGlobalSession(Long transactionId) throws TransactionException {
+                public GlobalSession findGlobalSession(Long transactionId) {
                     return null;
                 }
 
diff --git a/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java b/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java
index ad16e61da7938daf01c1c0690511a6cd89a87858..e437087f00f7f779e83f83df3b7f27507057d709 100644
--- a/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java
+++ b/server/src/test/java/io/seata/server/UUIDGeneratorOverflowTest.java
@@ -15,7 +15,7 @@
  */
 package io.seata.server;
 
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Uuid generator overflow test.
@@ -34,4 +34,4 @@ public class UUIDGeneratorOverflowTest {
             System.out.println("[UUID " + i + "] is: " + UUIDGenerator.generateUUID());
         }
     }
-}
\ No newline at end of file
+}
diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java
index 2a335283ceddc35d7970b7bb828b2423287ad442..d68dcf16bb5cd4622c9f1df36e7fc1fe1ec07b0b 100644
--- a/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java
+++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoordinatorTest.java
@@ -15,6 +15,7 @@
  */
 package io.seata.server.coordinator;
 
+import io.netty.channel.Channel;
 import io.seata.common.XID;
 import io.seata.common.util.NetUtil;
 import io.seata.core.exception.TransactionException;
@@ -27,16 +28,18 @@ import io.seata.core.protocol.transaction.BranchRollbackResponse;
 import io.seata.core.rpc.ServerMessageSender;
 import io.seata.server.session.GlobalSession;
 import io.seata.server.session.SessionHolder;
-import io.netty.channel.Channel;
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import java.io.IOException;
 import java.util.Collection;
 import java.util.concurrent.TimeoutException;
+import java.util.stream.Stream;
 
 /**
  * The type DefaultCoordinator test.
@@ -67,7 +70,7 @@ public class DefaultCoordinatorTest {
 
     private static Core core = new DefaultCore();
 
-    @BeforeClass
+    @BeforeAll
     public static void beforeClass() throws Exception {
         XID.setIpAddress(NetUtil.getLocalIp());
         SessionHolder.init(null);
@@ -76,33 +79,33 @@ public class DefaultCoordinatorTest {
         defaultCoordinator.init();
     }
 
-    @Test(dataProvider = "xidAndBranchIdProviderForCommit")
+    @ParameterizedTest
+    @MethodSource("xidAndBranchIdProviderForCommit")
     public void branchCommit(String xid, Long branchId) {
         BranchStatus result = null;
 
         try {
             result = defaultCoordinator.branchCommit(BranchType.AT, xid, branchId, resourceId, applicationData);
         } catch (TransactionException e) {
-            Assert.fail(e.getMessage());
+            Assertions.fail(e.getMessage());
         }
-        Assert.assertEquals(result, BranchStatus.PhaseTwo_Committed);
+        Assertions.assertEquals(result, BranchStatus.PhaseTwo_Committed);
 
     }
-
-    @Test(dataProvider = "xidAndBranchIdProviderForRollback")
+    @Disabled
+    @ParameterizedTest
+    @MethodSource("xidAndBranchIdProviderForRollback")
     public void branchRollback(String xid, Long branchId) {
         BranchStatus result = null;
         try {
             result = defaultCoordinator.branchRollback(BranchType.AT, xid, branchId, resourceId, applicationData);
         } catch (TransactionException e) {
-            Assert.fail(e.getMessage());
+            Assertions.fail(e.getMessage());
         }
-
-        Assert.assertEquals(result, BranchStatus.PhaseTwo_Rollbacked);
-
+        Assertions.assertEquals(result, BranchStatus.PhaseTwo_Rollbacked);
     }
 
-    @AfterClass
+    @AfterAll
     public static void afterClass() throws Exception {
 
         Collection<GlobalSession> globalSessions = SessionHolder.getRootSessionManager().allSessions();
@@ -115,19 +118,20 @@ public class DefaultCoordinatorTest {
         }
     }
 
-
-    @DataProvider
-    public static Object[][] xidAndBranchIdProviderForCommit() throws Exception {
+    static Stream<Arguments> xidAndBranchIdProviderForCommit() throws Exception {
         String xid = core.begin(applicationId, txServiceGroup, txName, timeout);
         Long branchId = core.branchRegister(BranchType.AT, resourceId, clientId, xid, applicationData, lockKeys_1);
-        return new Object[][]{{xid, branchId}};
+        return Stream.of(
+                Arguments.of(xid, branchId)
+        );
     }
 
-    @DataProvider
-    public static Object[][] xidAndBranchIdProviderForRollback() throws Exception {
+    static Stream<Arguments> xidAndBranchIdProviderForRollback() throws Exception {
         String xid = core.begin(applicationId, txServiceGroup, txName, timeout);
         Long branchId = core.branchRegister(BranchType.AT, resourceId, clientId, xid, applicationData, lockKeys_2);
-        return new Object[][]{{xid, branchId}};
+        return Stream.of(
+                Arguments.of(xid, branchId)
+        );
     }
 
 
@@ -160,4 +164,4 @@ public class DefaultCoordinatorTest {
 
         }
     }
-}
\ No newline at end of file
+}
diff --git a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java
index 760a3cef80801ed3ccd7a00ce87f0d87ecdaeba5..42b33e4ff5a4baf8ec36e0bfb4dc7b4b42b3c7a7 100644
--- a/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java
+++ b/server/src/test/java/io/seata/server/coordinator/DefaultCoreTest.java
@@ -24,13 +24,16 @@ import io.seata.core.model.ResourceManagerInbound;
 import io.seata.server.session.BranchSession;
 import io.seata.server.session.GlobalSession;
 import io.seata.server.session.SessionHolder;
-import org.testng.Assert;
-import org.testng.annotations.AfterTest;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import java.util.Collection;
+import java.util.stream.Stream;
 
 /**
  * The type Default core test.
@@ -65,7 +68,7 @@ public class DefaultCoreTest {
      *
      * @throws Exception the exception
      */
-    @BeforeTest
+    @BeforeEach
     public void initSessionManager() throws Exception {
         SessionHolder.init(null);
     }
@@ -76,12 +79,16 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void branchRegisterTest(String xid) throws Exception {
         core.branchRegister(BranchType.AT, resourceId, clientId, xid, "abc", lockKeys_1);
         long transactionId = XID.getTransactionId(xid);
         GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId);
-        Assert.assertEquals(globalSession.getSortedBranches().size(), 1);
+        Assertions.assertEquals(globalSession.getSortedBranches().size(), 1);
+
+        //clear
+        globalSession.end();
     }
 
     /**
@@ -91,13 +98,17 @@ public class DefaultCoreTest {
      * @param branchId the branch id
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidAndBranchIdProvider")
+    @ParameterizedTest
+    @MethodSource("xidAndBranchIdProvider")
     public void branchReportTest(String xid, Long branchId) throws Exception {
         core.branchReport(BranchType.AT, xid, branchId, BranchStatus.PhaseOne_Done, applicationData);
         long transactionId = XID.getTransactionId(xid);
         GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId);
         BranchSession branchSession = globalSession.getBranch(branchId);
-        Assert.assertEquals(branchSession.getStatus(), BranchStatus.PhaseOne_Done);
+        Assertions.assertEquals(branchSession.getStatus(), BranchStatus.PhaseOne_Done);
+
+        //clear
+        globalSession.end();
     }
 
     /**
@@ -110,7 +121,7 @@ public class DefaultCoreTest {
         String xid = core.begin(applicationId, txServiceGroup, txName, timeout);
         long transactionId = XID.getTransactionId(xid);
         GlobalSession globalSession = SessionHolder.findGlobalSession(transactionId);
-        Assert.assertNotNull(globalSession);
+        Assertions.assertNotNull(globalSession);
     }
 
     /**
@@ -119,10 +130,11 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void commitTest(String xid) throws Exception {
         GlobalStatus globalStatus = core.commit(xid);
-        Assert.assertNotEquals(globalStatus, GlobalStatus.Begin);
+        Assertions.assertNotEquals(globalStatus, GlobalStatus.Begin);
     }
 
     /**
@@ -131,7 +143,8 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void doGlobalCommitCommitTest(String xid) throws Exception {
         GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
         BranchSession branchSession = new BranchSession();
@@ -139,7 +152,10 @@ public class DefaultCoreTest {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done);
         core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseOne_Done));
         core.doGlobalCommit(globalSession, false);
-        Assert.assertEquals(globalSession.getStatus(), GlobalStatus.Committed);
+        Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.Committed);
+
+        //clear
+        globalSession.end();
     }
 
 
@@ -149,7 +165,8 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void doGlobalCommitUnretryableTest(String xid) throws Exception {
         GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
         BranchSession branchSession = new BranchSession();
@@ -157,7 +174,10 @@ public class DefaultCoreTest {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done);
         core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_CommitFailed_Unretryable, BranchStatus.PhaseOne_Done));
         core.doGlobalCommit(globalSession, false);
-        Assert.assertEquals(globalSession.getStatus(), GlobalStatus.Begin);
+        Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.Begin);
+
+        //clear
+        globalSession.end();
     }
 
     /**
@@ -166,7 +186,8 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void doGlobalCommitExpTest(String xid) throws Exception {
         GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
         BranchSession branchSession = new BranchSession();
@@ -174,7 +195,10 @@ public class DefaultCoreTest {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done);
         core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseOne_Timeout, BranchStatus.PhaseOne_Done));
         core.doGlobalCommit(globalSession, false);
-        Assert.assertEquals(globalSession.getStatus(), GlobalStatus.CommitRetrying);
+        Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.CommitRetrying);
+
+        //clear
+        globalSession.end();
     }
 
     /**
@@ -183,10 +207,11 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void rollBackTest(String xid) throws Exception {
         GlobalStatus globalStatus = core.rollback(xid);
-        Assert.assertEquals(globalStatus, GlobalStatus.Rollbacked);
+        Assertions.assertEquals(globalStatus, GlobalStatus.Rollbacked);
     }
 
     /**
@@ -195,7 +220,8 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void doGlobalRollBackRollbackedTest(String xid) throws Exception {
         GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
         BranchSession branchSession = new BranchSession();
@@ -203,7 +229,10 @@ public class DefaultCoreTest {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done);
         core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_Rollbacked));
         core.doGlobalRollback(globalSession, false);
-        Assert.assertEquals(globalSession.getStatus(), GlobalStatus.Rollbacked);
+        Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.Rollbacked);
+
+        //clear
+        globalSession.end();
     }
 
 
@@ -213,7 +242,8 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void doGlobalRollBackUnretryableTest(String xid) throws Exception {
         GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
         BranchSession branchSession = new BranchSession();
@@ -221,7 +251,10 @@ public class DefaultCoreTest {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done);
         core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_RollbackFailed_Unretryable));
         core.doGlobalRollback(globalSession, false);
-        Assert.assertEquals(globalSession.getStatus(), GlobalStatus.RollbackFailed);
+        Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.RollbackFailed);
+
+        //clear
+        globalSession.end();
     }
 
     /**
@@ -230,7 +263,8 @@ public class DefaultCoreTest {
      * @param xid the xid
      * @throws Exception the exception
      */
-    @Test(dataProvider = "xidProvider")
+    @ParameterizedTest
+    @MethodSource("xidProvider")
     public void doGlobalRollBackRetryableExpTest(String xid) throws Exception {
         GlobalSession globalSession = SessionHolder.findGlobalSession(XID.getTransactionId(xid));
         BranchSession branchSession = new BranchSession();
@@ -238,7 +272,9 @@ public class DefaultCoreTest {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseOne_Done);
         core.setResourceManagerInbound(new MockResourceManagerInbound(BranchStatus.PhaseTwo_Committed, BranchStatus.PhaseTwo_RollbackFailed_Retryable));
         core.doGlobalRollback(globalSession, false);
-        Assert.assertEquals(globalSession.getStatus(), GlobalStatus.RollbackRetrying);
+        Assertions.assertEquals(globalSession.getStatus(), GlobalStatus.RollbackRetrying);
+
+        globalSession.end();
     }
 
     /**
@@ -247,10 +283,11 @@ public class DefaultCoreTest {
      * @return the object [ ] [ ]
      * @throws Exception the exception
      */
-    @DataProvider
-    public static Object[][] xidProvider() throws Exception {
+    static Stream<Arguments> xidProvider() throws Exception {
         String xid = core.begin(applicationId, txServiceGroup, txName, timeout);
-        return new Object[][]{{xid}};
+        return Stream.of(
+                Arguments.of(xid)
+        );
     }
 
     /**
@@ -259,11 +296,12 @@ public class DefaultCoreTest {
      * @return the object [ ] [ ]
      * @throws Exception the exception
      */
-    @DataProvider
-    public static Object[][] xidAndBranchIdProvider() throws Exception {
+    static Stream<Arguments> xidAndBranchIdProvider() throws Exception {
         String xid = core.begin(applicationId, txServiceGroup, txName, timeout);
         Long branchId = core.branchRegister(BranchType.AT, resourceId, clientId, xid, null, lockKeys_2);
-        return new Object[][]{{xid, branchId}};
+        return Stream.of(
+                Arguments.of(xid, branchId)
+        );
     }
 
     /**
@@ -271,7 +309,7 @@ public class DefaultCoreTest {
      *
      * @throws Exception the exception
      */
-    @AfterTest
+    @AfterEach
     public void releaseSessionManager() throws Exception {
         Collection<GlobalSession> globalSessions = SessionHolder.getRootSessionManager().allSessions();
         Collection<GlobalSession> asyncGlobalSessions = SessionHolder.getAsyncCommittingSessionManager().allSessions();
diff --git a/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java b/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java
index 73207bdf6bc3da3d331b1ca0c77244ceac0bad8f..fbe0c216b420e65f1bad9de08a3210277ef004c7 100644
--- a/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java
+++ b/server/src/test/java/io/seata/server/lock/DefaultLockManagerImplTest.java
@@ -18,10 +18,12 @@ package io.seata.server.lock;
 import io.seata.core.model.BranchType;
 import io.seata.server.UUIDGenerator;
 import io.seata.server.session.BranchSession;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.stream.Stream;
 
 /**
  * The type Default lock manager impl test.
@@ -45,10 +47,11 @@ public class DefaultLockManagerImplTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void acquireLockTest(BranchSession branchSession) throws Exception {
         boolean result = lockManager.acquireLock(branchSession);
-        Assert.assertTrue(result);
+        Assertions.assertTrue(result);
         branchSession.unlock();
     }
 
@@ -60,16 +63,15 @@ public class DefaultLockManagerImplTest {
     @Test
     public void isLockableTest() throws Exception {
         boolean resultOne = lockManager.isLockable(transactionId, resourceId, lockKey);
-        Assert.assertTrue(resultOne);
+        Assertions.assertTrue(resultOne);
     }
 
     /**
      * Branch session provider object [ ] [ ].
      *
-     * @return the object [ ] [ ]
+     * @return Stream<BranchSession>
      */
-    @DataProvider
-    public static Object[][] branchSessionProvider() {
+    static Stream<BranchSession> branchSessionProvider() {
         BranchSession branchSession = new BranchSession();
         branchSession.setBranchId(1L);
         branchSession.setTransactionId(transactionId);
@@ -80,7 +82,7 @@ public class DefaultLockManagerImplTest {
         branchSession.setBranchType(BranchType.AT);
         branchSession.setApplicationData("{\"data\":\"test\"}");
         branchSession.setBranchType(BranchType.AT);
-        return new Object[][] {{branchSession}};
+        return Stream.of(branchSession);
     }
 
 }
diff --git a/server/src/test/java/io/seata/server/lock/LockManagerTest.java b/server/src/test/java/io/seata/server/lock/LockManagerTest.java
index 9ebee0ef72e8164def7f40bd1b689ae021067505..31084b1358ae24226a769d6dd89ae289e627713d 100644
--- a/server/src/test/java/io/seata/server/lock/LockManagerTest.java
+++ b/server/src/test/java/io/seata/server/lock/LockManagerTest.java
@@ -18,10 +18,12 @@ package io.seata.server.lock;
 import io.seata.core.model.BranchType;
 import io.seata.server.UUIDGenerator;
 import io.seata.server.session.BranchSession;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.junit.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.stream.Stream;
 
 /**
  * The type Lock manager test.
@@ -37,10 +39,11 @@ public class LockManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void acquireLock_success(BranchSession branchSession) throws Exception {
         LockManager lockManager = LockManagerFactory.get();
-        Assert.assertTrue(lockManager.acquireLock(branchSession));
+        Assertions.assertTrue(lockManager.acquireLock(branchSession));
     }
 
     /**
@@ -50,11 +53,12 @@ public class LockManagerTest {
      * @param branchSession2 the branch session 2
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionsProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionsProvider")
     public void acquireLock_failed(BranchSession branchSession1, BranchSession branchSession2) throws Exception {
         LockManager lockManager = LockManagerFactory.get();
-        Assert.assertTrue(lockManager.acquireLock(branchSession1));
-        Assert.assertFalse(lockManager.acquireLock(branchSession2));
+        Assertions.assertTrue(lockManager.acquireLock(branchSession1));
+        Assertions.assertFalse(lockManager.acquireLock(branchSession2));
     }
 
     /**
@@ -63,16 +67,17 @@ public class LockManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void isLockableTest(BranchSession branchSession) throws Exception {
         branchSession.setLockKey("t:4");
         LockManager lockManager = LockManagerFactory.get();
-        Assert.assertTrue(lockManager
-            .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey()));
+        Assertions.assertTrue(lockManager
+                .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey()));
         lockManager.acquireLock(branchSession);
         branchSession.setTransactionId(UUIDGenerator.generateUUID());
-        Assert.assertFalse(lockManager
-            .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey()));
+        Assertions.assertFalse(lockManager
+                .isLockable(branchSession.getTransactionId(), branchSession.getResourceId(), branchSession.getLockKey()));
     }
 
     /**
@@ -80,8 +85,7 @@ public class LockManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionProvider() {
+    static Stream<Arguments> branchSessionProvider() {
         BranchSession branchSession = new BranchSession();
         branchSession.setTransactionId(UUIDGenerator.generateUUID());
         branchSession.setBranchId(0L);
@@ -92,7 +96,8 @@ public class LockManagerTest {
         branchSession.setBranchType(BranchType.AT);
         branchSession.setApplicationData("{\"data\":\"test\"}");
         branchSession.setBranchType(BranchType.AT);
-        return new Object[][] {{branchSession}};
+        return Stream.of(
+                Arguments.of(branchSession));
     }
 
     /**
@@ -100,8 +105,7 @@ public class LockManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionsProvider() {
+    static Stream<Arguments> branchSessionsProvider() {
         BranchSession branchSession1 = new BranchSession();
         branchSession1.setTransactionId(UUIDGenerator.generateUUID());
         branchSession1.setBranchId(1L);
@@ -123,6 +127,7 @@ public class LockManagerTest {
         branchSession2.setBranchType(BranchType.AT);
         branchSession2.setApplicationData("{\"data\":\"test\"}");
         branchSession2.setBranchType(BranchType.AT);
-        return new Object[][] {{branchSession1, branchSession2}};
+        return Stream.of(
+                Arguments.of(branchSession1, branchSession2));
     }
 }
diff --git a/server/src/test/java/io/seata/server/session/BranchSessionTest.java b/server/src/test/java/io/seata/server/session/BranchSessionTest.java
index 231d6d588a4d28941a64e8f0cd847f38627a0105..d025f93a92d0f5da9b770de9cc850ab1f13dd6ee 100644
--- a/server/src/test/java/io/seata/server/session/BranchSessionTest.java
+++ b/server/src/test/java/io/seata/server/session/BranchSessionTest.java
@@ -17,10 +17,12 @@ package io.seata.server.session;
 
 import io.seata.core.model.BranchType;
 import io.seata.server.UUIDGenerator;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.stream.Stream;
 
 /**
  * The type Branch session test.
@@ -35,18 +37,19 @@ public class BranchSessionTest {
      *
      * @param branchSession the branch session
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void codecTest(BranchSession branchSession) {
         byte[] result = branchSession.encode();
-        Assert.assertNotNull(result);
+        Assertions.assertNotNull(result);
         BranchSession expected = new BranchSession();
         expected.decode(result);
-        Assert.assertEquals(branchSession.getTransactionId(), expected.getTransactionId());
-        Assert.assertEquals(branchSession.getBranchId(), expected.getBranchId());
-        Assert.assertEquals(branchSession.getResourceId(), expected.getResourceId());
-        Assert.assertEquals(branchSession.getLockKey(), expected.getLockKey());
-        Assert.assertEquals(branchSession.getClientId(), expected.getClientId());
-        Assert.assertEquals(branchSession.getApplicationData(), expected.getApplicationData());
+        Assertions.assertEquals(branchSession.getTransactionId(), expected.getTransactionId());
+        Assertions.assertEquals(branchSession.getBranchId(), expected.getBranchId());
+        Assertions.assertEquals(branchSession.getResourceId(), expected.getResourceId());
+        Assertions.assertEquals(branchSession.getLockKey(), expected.getLockKey());
+        Assertions.assertEquals(branchSession.getClientId(), expected.getClientId());
+        Assertions.assertEquals(branchSession.getApplicationData(), expected.getApplicationData());
 
     }
 
@@ -55,8 +58,7 @@ public class BranchSessionTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionProvider() {
+    static Stream<Arguments> branchSessionProvider() {
         BranchSession branchSession = new BranchSession();
         branchSession.setTransactionId(UUIDGenerator.generateUUID());
         branchSession.setBranchId(1L);
@@ -67,6 +69,8 @@ public class BranchSessionTest {
         branchSession.setBranchType(BranchType.AT);
         branchSession.setApplicationData("{\"data\":\"test\"}");
         branchSession.setBranchType(BranchType.AT);
-        return new Object[][] {{branchSession}};
+        return Stream.of(
+                Arguments.of(branchSession)
+        );
     }
 }
diff --git a/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java b/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java
index 790db9490150d9364521ed4c4e7b6036beeb0a80..33544245aa50756ecc6782aeb03dc29360cc7e65 100644
--- a/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java
+++ b/server/src/test/java/io/seata/server/session/DefaultSessionManagerTest.java
@@ -15,18 +15,18 @@
  */
 package io.seata.server.session;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
 import io.seata.core.model.BranchStatus;
 import io.seata.core.model.BranchType;
 import io.seata.core.model.GlobalStatus;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Stream;
 
 /**
  * The type Default session manager test.
@@ -44,7 +44,8 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void addGlobalSessionTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.removeGlobalSession(globalSession);
@@ -56,17 +57,18 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void findGlobalSessionTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId());
-        Assert.assertNotNull(expected);
-        Assert.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
-        Assert.assertEquals(expected.getApplicationId(), globalSession.getApplicationId());
-        Assert.assertEquals(expected.getTransactionServiceGroup(), globalSession.getTransactionServiceGroup());
-        Assert.assertEquals(expected.getTransactionName(), globalSession.getTransactionName());
-        Assert.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
-        Assert.assertEquals(expected.getStatus(), globalSession.getStatus());
+        Assertions.assertNotNull(expected);
+        Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
+        Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId());
+        Assertions.assertEquals(expected.getTransactionServiceGroup(), globalSession.getTransactionServiceGroup());
+        Assertions.assertEquals(expected.getTransactionName(), globalSession.getTransactionName());
+        Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
+        Assertions.assertEquals(expected.getStatus(), globalSession.getStatus());
         sessionManager.removeGlobalSession(globalSession);
     }
 
@@ -76,14 +78,15 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         globalSession.setStatus(GlobalStatus.Finished);
         sessionManager.updateGlobalSessionStatus(globalSession, GlobalStatus.Finished);
         GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId());
-        Assert.assertNotNull(expected);
-        Assert.assertEquals(GlobalStatus.Finished, expected.getStatus());
+        Assertions.assertNotNull(expected);
+        Assertions.assertEquals(GlobalStatus.Finished, expected.getStatus());
         sessionManager.removeGlobalSession(globalSession);
     }
 
@@ -93,12 +96,13 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void removeGlobalSessionTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.removeGlobalSession(globalSession);
         GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId());
-        Assert.assertNull(expected);
+        Assertions.assertNull(expected);
 
     }
 
@@ -109,7 +113,8 @@ public class DefaultSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void addBranchSessionTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.addBranchSession(globalSession, branchSession);
@@ -124,9 +129,10 @@ public class DefaultSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void updateBranchSessionStatusTest(GlobalSession globalSession, BranchSession branchSession)
-        throws Exception {
+            throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.addBranchSession(globalSession, branchSession);
         sessionManager.updateBranchSessionStatus(branchSession, BranchStatus.PhaseTwo_Committed);
@@ -141,7 +147,8 @@ public class DefaultSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void removeBranchSessionTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.addBranchSession(globalSession, branchSession);
@@ -155,14 +162,15 @@ public class DefaultSessionManagerTest {
      * @param globalSessions the global sessions
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionsProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionsProvider")
     public void allSessionsTest(List<GlobalSession> globalSessions) throws Exception {
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.addGlobalSession(globalSession);
         }
         Collection<GlobalSession> expectedGlobalSessions = sessionManager.allSessions();
-        Assert.assertNotNull(expectedGlobalSessions);
-        Assert.assertEquals(2, expectedGlobalSessions.size());
+        Assertions.assertNotNull(expectedGlobalSessions);
+        Assertions.assertEquals(2, expectedGlobalSessions.size());
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.removeGlobalSession(globalSession);
         }
@@ -174,15 +182,16 @@ public class DefaultSessionManagerTest {
      * @param globalSessions the global sessions
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionsProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionsProvider")
     public void findGlobalSessionsTest(List<GlobalSession> globalSessions) throws Exception {
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.addGlobalSession(globalSession);
         }
-        SessionCondition sessionCondition = new SessionCondition( 30 * 24 * 3600);
+        SessionCondition sessionCondition = new SessionCondition(30 * 24 * 3600);
         Collection<GlobalSession> expectedGlobalSessions = sessionManager.findGlobalSessions(sessionCondition);
-        Assert.assertNotNull(expectedGlobalSessions);
-        Assert.assertEquals(2, expectedGlobalSessions.size());
+        Assertions.assertNotNull(expectedGlobalSessions);
+        Assertions.assertEquals(2, expectedGlobalSessions.size());
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.removeGlobalSession(globalSession);
         }
@@ -194,7 +203,8 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onBeginTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onEnd(globalSession);
@@ -206,7 +216,8 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onStatusChangeTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onStatusChange(globalSession, GlobalStatus.Finished);
@@ -220,7 +231,8 @@ public class DefaultSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void onBranchStatusChangeTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onAddBranch(globalSession, branchSession);
@@ -234,7 +246,8 @@ public class DefaultSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void onAddBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onAddBranch(globalSession, branchSession);
@@ -247,7 +260,8 @@ public class DefaultSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void onRemoveBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onAddBranch(globalSession, branchSession);
@@ -260,7 +274,8 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onCloseTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onClose(globalSession);
@@ -272,7 +287,8 @@ public class DefaultSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onEndTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onEnd(globalSession);
@@ -283,10 +299,11 @@ public class DefaultSessionManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] globalSessionProvider() {
+    static Stream<Arguments> globalSessionProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
-        return new Object[][] {{globalSession}};
+        return Stream.of(
+                Arguments.of(globalSession)
+        );
     }
 
     /**
@@ -294,11 +311,12 @@ public class DefaultSessionManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] globalSessionsProvider() {
+    static Stream<Arguments> globalSessionsProvider() {
         GlobalSession globalSession1 = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         GlobalSession globalSession2 = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
-        return new Object[][] {{Arrays.asList(globalSession1, globalSession2)}};
+        return Stream.of(
+                Arguments.of(Arrays.asList(globalSession1, globalSession2))
+        );
     }
 
     /**
@@ -306,8 +324,7 @@ public class DefaultSessionManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionProvider() {
+    static Stream<Arguments> branchSessionProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         BranchSession branchSession = new BranchSession();
         branchSession.setTransactionId(globalSession.getTransactionId());
@@ -317,6 +334,8 @@ public class DefaultSessionManagerTest {
         branchSession.setLockKey("t_1");
         branchSession.setBranchType(BranchType.AT);
         branchSession.setApplicationData("{\"data\":\"test\"}");
-        return new Object[][] {{globalSession, branchSession}};
+        return Stream.of(
+                Arguments.of(globalSession, branchSession)
+        );
     }
 }
diff --git a/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java b/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java
index 54b00ce6e11624ce09234fc14241ef07d72073ca..803f1200c47376936c91e23e91ddbf041a3e6674 100644
--- a/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java
+++ b/server/src/test/java/io/seata/server/session/FileBasedSessionManagerTest.java
@@ -15,18 +15,19 @@
  */
 package io.seata.server.session;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
 import io.seata.core.model.BranchStatus;
 import io.seata.core.model.BranchType;
 import io.seata.core.model.GlobalStatus;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.testng.Assert;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Stream;
 
 /**
  * The type File based session manager test.
@@ -36,14 +37,14 @@ import org.testng.annotations.Test;
  */
 public class FileBasedSessionManagerTest {
 
-    private SessionManager sessionManager = null;
+    private static SessionManager sessionManager = null;
 
     /**
      * Sets up.
      *
      * @throws Exception the exception
      */
-    @BeforeClass
+    @BeforeEach
     public void setUp() throws Exception {
         sessionManager = new FileBasedSessionManager("root.data", ".");
     }
@@ -54,7 +55,8 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void addGlobalSessionTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.removeGlobalSession(globalSession);
@@ -66,17 +68,18 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void findGlobalSessionTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId());
-        Assert.assertNotNull(expected);
-        Assert.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
-        Assert.assertEquals(expected.getApplicationId(), globalSession.getApplicationId());
-        Assert.assertEquals(expected.getTransactionServiceGroup(), globalSession.getTransactionServiceGroup());
-        Assert.assertEquals(expected.getTransactionName(), globalSession.getTransactionName());
-        Assert.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
-        Assert.assertEquals(expected.getStatus(), globalSession.getStatus());
+        Assertions.assertNotNull(expected);
+        Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
+        Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId());
+        Assertions.assertEquals(expected.getTransactionServiceGroup(), globalSession.getTransactionServiceGroup());
+        Assertions.assertEquals(expected.getTransactionName(), globalSession.getTransactionName());
+        Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
+        Assertions.assertEquals(expected.getStatus(), globalSession.getStatus());
         sessionManager.removeGlobalSession(globalSession);
     }
 
@@ -86,14 +89,15 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void updateGlobalSessionStatusTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         globalSession.setStatus(GlobalStatus.Finished);
         sessionManager.updateGlobalSessionStatus(globalSession, GlobalStatus.Finished);
         GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId());
-        Assert.assertNotNull(expected);
-        Assert.assertEquals(GlobalStatus.Finished, expected.getStatus());
+        Assertions.assertNotNull(expected);
+        Assertions.assertEquals(GlobalStatus.Finished, expected.getStatus());
         sessionManager.removeGlobalSession(globalSession);
     }
 
@@ -103,12 +107,13 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void removeGlobalSessionTest(GlobalSession globalSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.removeGlobalSession(globalSession);
         GlobalSession expected = sessionManager.findGlobalSession(globalSession.getTransactionId());
-        Assert.assertNull(expected);
+        Assertions.assertNull(expected);
 
     }
 
@@ -119,7 +124,8 @@ public class FileBasedSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void addBranchSessionTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.addBranchSession(globalSession, branchSession);
@@ -134,9 +140,10 @@ public class FileBasedSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void updateBranchSessionStatusTest(GlobalSession globalSession, BranchSession branchSession)
-        throws Exception {
+            throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.addBranchSession(globalSession, branchSession);
         sessionManager.updateBranchSessionStatus(branchSession, BranchStatus.PhaseTwo_Committed);
@@ -151,7 +158,8 @@ public class FileBasedSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void removeBranchSessionTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.addGlobalSession(globalSession);
         sessionManager.addBranchSession(globalSession, branchSession);
@@ -165,14 +173,15 @@ public class FileBasedSessionManagerTest {
      * @param globalSessions the global sessions
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionsProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionsProvider")
     public void allSessionsTest(List<GlobalSession> globalSessions) throws Exception {
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.addGlobalSession(globalSession);
         }
         Collection<GlobalSession> expectedGlobalSessions = sessionManager.allSessions();
-        Assert.assertNotNull(expectedGlobalSessions);
-        Assert.assertEquals(2, expectedGlobalSessions.size());
+        Assertions.assertNotNull(expectedGlobalSessions);
+        Assertions.assertEquals(2, expectedGlobalSessions.size());
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.removeGlobalSession(globalSession);
         }
@@ -184,15 +193,16 @@ public class FileBasedSessionManagerTest {
      * @param globalSessions the global sessions
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionsProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionsProvider")
     public void findGlobalSessionsTest(List<GlobalSession> globalSessions) throws Exception {
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.addGlobalSession(globalSession);
         }
-        SessionCondition sessionCondition = new SessionCondition( 30 * 24 * 3600);
+        SessionCondition sessionCondition = new SessionCondition(30 * 24 * 3600);
         Collection<GlobalSession> expectedGlobalSessions = sessionManager.findGlobalSessions(sessionCondition);
-        Assert.assertNotNull(expectedGlobalSessions);
-        Assert.assertEquals(2, expectedGlobalSessions.size());
+        Assertions.assertNotNull(expectedGlobalSessions);
+        Assertions.assertEquals(2, expectedGlobalSessions.size());
         for (GlobalSession globalSession : globalSessions) {
             sessionManager.removeGlobalSession(globalSession);
         }
@@ -204,7 +214,8 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onBeginTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onEnd(globalSession);
@@ -216,7 +227,8 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onStatusChangeTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onStatusChange(globalSession, GlobalStatus.Finished);
@@ -230,7 +242,8 @@ public class FileBasedSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void onBranchStatusChangeTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onAddBranch(globalSession, branchSession);
@@ -244,7 +257,8 @@ public class FileBasedSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void onAddBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onAddBranch(globalSession, branchSession);
@@ -257,7 +271,8 @@ public class FileBasedSessionManagerTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void onRemoveBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onAddBranch(globalSession, branchSession);
@@ -270,7 +285,8 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onCloseTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onClose(globalSession);
@@ -282,7 +298,8 @@ public class FileBasedSessionManagerTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void onEndTest(GlobalSession globalSession) throws Exception {
         sessionManager.onBegin(globalSession);
         sessionManager.onEnd(globalSession);
@@ -293,10 +310,11 @@ public class FileBasedSessionManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] globalSessionProvider() {
+    static Stream<Arguments> globalSessionProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
-        return new Object[][] {{globalSession}};
+        return Stream.of(
+                Arguments.of(globalSession)
+        );
     }
 
     /**
@@ -304,11 +322,12 @@ public class FileBasedSessionManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] globalSessionsProvider() {
+    static Stream<Arguments> globalSessionsProvider() {
         GlobalSession globalSession1 = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         GlobalSession globalSession2 = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
-        return new Object[][] {{Arrays.asList(globalSession1, globalSession2)}};
+        return Stream.of(
+                Arguments.of(Arrays.asList(globalSession1, globalSession2))
+        );
     }
 
     /**
@@ -316,8 +335,7 @@ public class FileBasedSessionManagerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionProvider() {
+    static Stream<Arguments> branchSessionProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         BranchSession branchSession = new BranchSession();
         branchSession.setTransactionId(globalSession.getTransactionId());
@@ -327,6 +345,8 @@ public class FileBasedSessionManagerTest {
         branchSession.setLockKey("t_1");
         branchSession.setBranchType(BranchType.AT);
         branchSession.setApplicationData("{\"data\":\"test\"}");
-        return new Object[][] {{globalSession, branchSession}};
+        return Stream.of(
+                Arguments.of(globalSession, branchSession)
+        );
     }
 }
diff --git a/server/src/test/java/io/seata/server/session/GlobalSessionTest.java b/server/src/test/java/io/seata/server/session/GlobalSessionTest.java
index 33356716912445d14955ca8bd26d251828b71cf6..ee0404eeb38fc014d368aa028b161178e2508f51 100644
--- a/server/src/test/java/io/seata/server/session/GlobalSessionTest.java
+++ b/server/src/test/java/io/seata/server/session/GlobalSessionTest.java
@@ -18,10 +18,12 @@ package io.seata.server.session;
 import io.seata.core.model.BranchStatus;
 import io.seata.core.model.BranchType;
 import io.seata.core.model.GlobalStatus;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import java.util.stream.Stream;
 
 /**
  * The type Global session test.
@@ -36,9 +38,10 @@ public class GlobalSessionTest {
      *
      * @param globalSession the global session
      */
-    @Test(dataProvider = "branchSessionTCCProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionTCCProvider")
     public void canBeCommittedAsyncTest(GlobalSession globalSession) {
-        Assert.assertFalse(globalSession.canBeCommittedAsync());
+        Assertions.assertFalse(globalSession.canBeCommittedAsync());
     }
 
     /**
@@ -47,7 +50,8 @@ public class GlobalSessionTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void beginTest(GlobalSession globalSession) throws Exception {
         globalSession.begin();
     }
@@ -58,7 +62,8 @@ public class GlobalSessionTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void changeStatusTest(GlobalSession globalSession) throws Exception {
         globalSession.changeStatus(GlobalStatus.Committed);
     }
@@ -70,7 +75,8 @@ public class GlobalSessionTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void changeBranchStatusTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         globalSession.changeBranchStatus(branchSession, BranchStatus.PhaseTwo_Committed);
     }
@@ -81,7 +87,8 @@ public class GlobalSessionTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void closeTest(GlobalSession globalSession) throws Exception {
         globalSession.close();
     }
@@ -92,7 +99,8 @@ public class GlobalSessionTest {
      * @param globalSession the global session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void endTest(GlobalSession globalSession) throws Exception {
         globalSession.end();
     }
@@ -104,7 +112,8 @@ public class GlobalSessionTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void addBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         globalSession.addBranch(branchSession);
     }
@@ -116,7 +125,8 @@ public class GlobalSessionTest {
      * @param branchSession the branch session
      * @throws Exception the exception
      */
-    @Test(dataProvider = "branchSessionProvider")
+    @ParameterizedTest
+    @MethodSource("branchSessionProvider")
     public void removeBranchTest(GlobalSession globalSession, BranchSession branchSession) throws Exception {
         globalSession.addBranch(branchSession);
         globalSession.removeBranch(branchSession);
@@ -127,17 +137,18 @@ public class GlobalSessionTest {
      *
      * @param globalSession the global session
      */
-    @Test(dataProvider = "globalSessionProvider")
+    @ParameterizedTest
+    @MethodSource("globalSessionProvider")
     public void codecTest(GlobalSession globalSession) {
         byte[] result = globalSession.encode();
-        Assert.assertNotNull(result);
+        Assertions.assertNotNull(result);
         GlobalSession expected = new GlobalSession();
         expected.decode(result);
-        Assert.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
-        Assert.assertEquals(expected.getTimeout(), globalSession.getTimeout());
-        Assert.assertEquals(expected.getApplicationId(), globalSession.getApplicationId());
-        Assert.assertEquals(expected.getTransactionServiceGroup(), globalSession.getTransactionServiceGroup());
-        Assert.assertEquals(expected.getTransactionName(), globalSession.getTransactionName());
+        Assertions.assertEquals(expected.getTransactionId(), globalSession.getTransactionId());
+        Assertions.assertEquals(expected.getTimeout(), globalSession.getTimeout());
+        Assertions.assertEquals(expected.getApplicationId(), globalSession.getApplicationId());
+        Assertions.assertEquals(expected.getTransactionServiceGroup(), globalSession.getTransactionServiceGroup());
+        Assertions.assertEquals(expected.getTransactionName(), globalSession.getTransactionName());
     }
 
     /**
@@ -145,12 +156,14 @@ public class GlobalSessionTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] globalSessionProvider() {
+    static Stream<Arguments> globalSessionProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         globalSession.setActive(true);
         globalSession.addSessionLifecycleListener(new DefaultSessionManager("default"));
-        return new Object[][] {{globalSession}};
+        return Stream.of(
+                Arguments.of(
+                        globalSession)
+        );
     }
 
     /**
@@ -158,8 +171,7 @@ public class GlobalSessionTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionProvider() {
+    static Stream<Arguments> branchSessionProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         BranchSession branchSession = new BranchSession();
         branchSession.setTransactionId(globalSession.getTransactionId());
@@ -170,7 +182,10 @@ public class GlobalSessionTest {
         branchSession.setBranchType(BranchType.AT);
         branchSession.setApplicationData("{\"data\":\"test\"}");
         globalSession.add(branchSession);
-        return new Object[][] {{globalSession, branchSession}};
+        return Stream.of(
+                Arguments.of(
+                        globalSession, branchSession)
+        );
     }
 
     /**
@@ -178,8 +193,8 @@ public class GlobalSessionTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] branchSessionTCCProvider() {
+
+    static Stream<Arguments> branchSessionTCCProvider() {
         GlobalSession globalSession = new GlobalSession("demo-app", "my_test_tx_group", "test", 6000);
         BranchSession branchSession = new BranchSession();
         branchSession.setTransactionId(globalSession.getTransactionId());
@@ -190,6 +205,8 @@ public class GlobalSessionTest {
         branchSession.setBranchType(BranchType.TCC);
         branchSession.setApplicationData("{\"data\":\"test\"}");
         globalSession.add(branchSession);
-        return new Object[][] {{globalSession}};
+        return Stream.of(
+                Arguments.of(globalSession)
+        );
     }
 }
diff --git a/server/src/test/java/io/seata/server/session/SessionHolderTest.java b/server/src/test/java/io/seata/server/session/SessionHolderTest.java
index 2e10bd31a46dcc825e08994c7b388baad693f248..e4b5008ea685881cda3deed481859741ba82f666 100644
--- a/server/src/test/java/io/seata/server/session/SessionHolderTest.java
+++ b/server/src/test/java/io/seata/server/session/SessionHolderTest.java
@@ -17,10 +17,10 @@ package io.seata.server.session;
 
 import io.seata.core.constants.ConfigurationKeys;
 import io.seata.core.store.StoreMode;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import java.io.File;
 import java.io.IOException;
@@ -36,7 +36,7 @@ import static io.seata.server.session.SessionHolder.ROOT_SESSION_MANAGER_NAME;
 public class SessionHolderTest {
     private String pathname;
 
-    @Before
+    @BeforeEach
     public void before() {
         String sessionStorePath = SessionHolder.CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR);
         //delete file previously created
@@ -52,15 +52,15 @@ public class SessionHolderTest {
         final String mode = StoreMode.FILE.toString();
         SessionHolder.init(mode);
         final File actual = new File(pathname);
-        Assert.assertTrue(actual.exists());
-        Assert.assertTrue(actual.isFile());
+        Assertions.assertTrue(actual.exists());
+        Assertions.assertTrue(actual.isFile());
     }
 
-    @After
+    @AfterEach
     public void after() {
         final File actual = new File(pathname);
         if (actual.exists()) {
             actual.delete();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/server/src/test/java/io/seata/server/store/SessionStoreTest.java b/server/src/test/java/io/seata/server/store/SessionStoreTest.java
index e5addccd52382ba33f7025ff531b5bc63b4eaee2..45048d7f63da748e082bb35c3b5c4198596de8fa 100644
--- a/server/src/test/java/io/seata/server/store/SessionStoreTest.java
+++ b/server/src/test/java/io/seata/server/store/SessionStoreTest.java
@@ -15,8 +15,6 @@
  */
 package io.seata.server.store;
 
-import java.io.File;
-
 import io.seata.config.Configuration;
 import io.seata.config.ConfigurationFactory;
 import io.seata.core.constants.ConfigurationKeys;
@@ -29,10 +27,11 @@ import io.seata.server.session.BranchSession;
 import io.seata.server.session.GlobalSession;
 import io.seata.server.session.SessionHelper;
 import io.seata.server.session.SessionHolder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import org.junit.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
+import java.io.File;
 
 /**
  * The type Session store test.
@@ -52,7 +51,7 @@ public class SessionStoreTest {
      *
      * @throws Exception the exception
      */
-    @BeforeMethod
+    @BeforeEach
     public void clean() throws Exception {
         String sessionStorePath = CONFIG.getConfig(ConfigurationKeys.STORE_FILE_DIR);
         File rootDataFile = new File(sessionStorePath + File.separator + SessionHolder.ROOT_SESSION_MANAGER_NAME);
@@ -87,32 +86,32 @@ public class SessionStoreTest {
 
         LockManager lockManager = LockManagerFactory.get();
 
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
 
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:4"));
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:5"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:4"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:5"));
 
         lockManager.cleanAllLocks();
 
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
 
         // Re-init SessionHolder: restore sessions from file
         SessionHolder.init("file");
 
         long tid = globalSession.getTransactionId();
         GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
-        Assert.assertNotNull(reloadSession);
-        Assert.assertFalse(globalSession == reloadSession);
-        Assert.assertEquals(globalSession.getApplicationId(), reloadSession.getApplicationId());
+        Assertions.assertNotNull(reloadSession);
+        Assertions.assertFalse(globalSession == reloadSession);
+        Assertions.assertEquals(globalSession.getApplicationId(), reloadSession.getApplicationId());
 
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
-        Assert.assertTrue(lockManager.isLockable(globalSession.getTransactionId(), RESOURCE_ID, "tb:3"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:2"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "tb:3"));
+        Assertions.assertTrue(lockManager.isLockable(globalSession.getTransactionId(), RESOURCE_ID, "tb:3"));
 
         //clear
         reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
@@ -151,32 +150,32 @@ public class SessionStoreTest {
 
         BranchSession branchSession1 = SessionHelper.newBranchByGlobal(globalSession, BranchType.AT, RESOURCE_ID,
                 "ta:1", "xxx");
-        Assert.assertTrue(branchSession1.lock());
+        Assertions.assertTrue(branchSession1.lock());
         globalSession.addBranch(branchSession1);
 
         LockManager lockManager = LockManagerFactory.get();
 
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         globalSession.changeStatus(GlobalStatus.AsyncCommitting);
 
         lockManager.cleanAllLocks();
 
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         // Re-init SessionHolder: restore sessions from file
         SessionHolder.init("file");
 
         long tid = globalSession.getTransactionId();
         GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
-        Assert.assertEquals(reloadSession.getStatus(), GlobalStatus.AsyncCommitting);
+        Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.AsyncCommitting);
 
         GlobalSession sessionInAsyncCommittingQueue = SessionHolder.getAsyncCommittingSessionManager()
                 .findGlobalSession(tid);
-        Assert.assertTrue(reloadSession == sessionInAsyncCommittingQueue);
+        Assertions.assertTrue(reloadSession == sessionInAsyncCommittingQueue);
 
         // No locking for session in AsyncCommitting status
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         //clear
         reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
@@ -203,7 +202,7 @@ public class SessionStoreTest {
 
         LockManager lockManager = LockManagerFactory.get();
 
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         globalSession.changeStatus(GlobalStatus.Committing);
         globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Retryable);
@@ -211,23 +210,23 @@ public class SessionStoreTest {
 
         lockManager.cleanAllLocks();
 
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         // Re-init SessionHolder: restore sessions from file
         SessionHolder.init("file");
 
         long tid = globalSession.getTransactionId();
         GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
-        Assert.assertEquals(reloadSession.getStatus(), GlobalStatus.CommitRetrying);
+        Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.CommitRetrying);
 
         GlobalSession sessionInRetryCommittingQueue = SessionHolder.getRetryCommittingSessionManager()
                 .findGlobalSession(tid);
-        Assert.assertTrue(reloadSession == sessionInRetryCommittingQueue);
+        Assertions.assertTrue(reloadSession == sessionInRetryCommittingQueue);
         BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId());
-        Assert.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_CommitFailed_Retryable);
+        Assertions.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_CommitFailed_Retryable);
 
         // Lock is held by session in CommitRetrying status
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         //clear
         reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
@@ -255,7 +254,7 @@ public class SessionStoreTest {
 
         LockManager lockManager = LockManagerFactory.get();
 
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         globalSession.changeStatus(GlobalStatus.Rollbacking);
         globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_RollbackFailed_Retryable);
@@ -263,23 +262,23 @@ public class SessionStoreTest {
 
         lockManager.cleanAllLocks();
 
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         // Re-init SessionHolder: restore sessions from file
         SessionHolder.init("file");
 
         long tid = globalSession.getTransactionId();
         GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
-        Assert.assertEquals(reloadSession.getStatus(), GlobalStatus.RollbackRetrying);
+        Assertions.assertEquals(reloadSession.getStatus(), GlobalStatus.RollbackRetrying);
 
         GlobalSession sessionInRetryRollbackingQueue = SessionHolder.getRetryRollbackingSessionManager()
                 .findGlobalSession(tid);
-        Assert.assertTrue(reloadSession == sessionInRetryRollbackingQueue);
+        Assertions.assertTrue(reloadSession == sessionInRetryRollbackingQueue);
         BranchSession reloadBranchSession = reloadSession.getBranch(branchSession1.getBranchId());
-        Assert.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_RollbackFailed_Retryable);
+        Assertions.assertEquals(reloadBranchSession.getStatus(), BranchStatus.PhaseTwo_RollbackFailed_Retryable);
 
         // Lock is held by session in RollbackRetrying status
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         //clear
         reloadSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
@@ -307,24 +306,24 @@ public class SessionStoreTest {
 
         LockManager lockManager = LockManagerFactory.get();
 
-        Assert.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertFalse(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         globalSession.changeStatus(GlobalStatus.Rollbacking);
         globalSession.changeBranchStatus(branchSession1, BranchStatus.PhaseTwo_CommitFailed_Unretryable);
         SessionHelper.endRollbackFailed(globalSession);
 
         // Lock is released.
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         lockManager.cleanAllLocks();
 
-        Assert.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
+        Assertions.assertTrue(lockManager.isLockable(0L, RESOURCE_ID, "ta:1"));
 
         // Re-init SessionHolder: restore sessions from file
         SessionHolder.init("file");
 
         long tid = globalSession.getTransactionId();
         GlobalSession reloadSession = SessionHolder.findGlobalSession(tid);
-        Assert.assertNull(reloadSession);
+        Assertions.assertNull(reloadSession);
     }
 }
diff --git a/spring/pom.xml b/spring/pom.xml
index 85ef20c21408eb7beb60fea3dbb7a34a042e3cb7..8bfd78e3d57b33c4637b72e8ac63a8a5e4fbb77d 100644
--- a/spring/pom.xml
+++ b/spring/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -31,34 +31,46 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-tm</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-rm-datasource</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-tcc</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-rm</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
         </dependency>
 
+        <!-- spring  -->
         <dependency>
             <groupId>org.springframework</groupId>
-            <artifactId>spring</artifactId>
-            <scope>provided</scope>
+            <artifactId>spring-context</artifactId>
         </dependency>
         <dependency>
-            <groupId>cglib</groupId>
-            <artifactId>cglib</artifactId>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <scope>test</scope>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
         </dependency>
+
     </dependencies>
 
 
diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java
index aa92dabbe3174024c6551186952fbec02e05224d..1005c280774e71a1a23b08a6ae0ca08fcb2205a6 100644
--- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java
+++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionScanner.java
@@ -289,6 +289,7 @@ public class GlobalTransactionScanner extends AbstractAutoProxyCreator implement
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         this.applicationContext = applicationContext;
+        this.setBeanFactory(applicationContext);
     }
 
 }
diff --git a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java
index bc88a5435a9dd2572d33b33084593a70e1aae830..b3d7370e3d7f890498acd0aeba5972798a696b59 100644
--- a/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java
+++ b/spring/src/main/java/io/seata/spring/annotation/GlobalTransactionalInterceptor.java
@@ -38,7 +38,7 @@ import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.Set;
-import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
 
 /**
  * The type Global transactional interceptor.
@@ -84,17 +84,14 @@ public class GlobalTransactionalInterceptor implements MethodInterceptor {
     }
 
     private Object handleGlobalLock(final MethodInvocation methodInvocation) throws Exception {
-        return globalLockTemplate.execute(new Callable<Object>() {
-            @Override
-            public Object call() throws Exception {
-                try {
-                    return methodInvocation.proceed();
-                } catch (Throwable e) {
-                    if (e instanceof Exception) {
-                        throw (Exception)e;
-                    } else {
-                        throw new RuntimeException(e);
-                    }
+        return globalLockTemplate.execute(() -> {
+            try {
+                return methodInvocation.proceed();
+            } catch (Throwable e) {
+                if (e instanceof Exception) {
+                    throw (Exception)e;
+                } else {
+                    throw new RuntimeException(e);
                 }
             }
         });
@@ -170,8 +167,7 @@ public class GlobalTransactionalInterceptor implements MethodInterceptor {
     private String formatMethod(Method method) {
         String paramTypes = Arrays.stream(method.getParameterTypes())
                 .map(Class::getName)
-                .reduce((p1, p2) -> String.format("%s, %s", p1, p2))
-                .orElse("");
-        return method.getName() + "(" + paramTypes + ")";
+                .collect(Collectors.joining(", ", "(", ")"));
+        return method.getName() + paramTypes;
     }
 }
diff --git a/spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java b/spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java
index 6999738008d6137bd78aaaa79b01c1e0b62615c7..1ab5b9927bed049bf1635cd583bc467f4e25cc47 100644
--- a/spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java
+++ b/spring/src/test/java/io/seata/spring/annotation/GlobalTransactionScannerTest.java
@@ -19,9 +19,13 @@ import io.seata.spring.tcc.LocalTccAction;
 import io.seata.spring.tcc.LocalTccActionImpl;
 import io.seata.spring.tcc.TccAction;
 import io.seata.spring.tcc.TccActionImpl;
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
 
 /**
  * GlobalTransactionScanner Unit Test
@@ -35,40 +39,43 @@ public class GlobalTransactionScannerTest {
     /**
      * Test wrap normal bean.
      *
-     * @param bean the bean
+     * @param bean     the bean
      * @param beanName the bean name
      * @param cacheKey the cache key
      */
-    @Test(dataProvider = "normalBeanProvider")
+    @ParameterizedTest
+    @MethodSource("normalBeanProvider")
     public void testWrapNormalBean(Object bean, String beanName, Object cacheKey) {
         Object result = globalTransactionScanner.wrapIfNecessary(bean, beanName, cacheKey);
-        Assert.assertNotSame(result, bean);
+        Assertions.assertNotSame(result, bean);
     }
 
     /**
      * wrap nothing
      *
-     * @param bean the bean
+     * @param bean     the bean
      * @param beanName the bean name
      * @param cacheKey the cache key
      */
-    @Test(dataProvider = "normalTccBeanProvider")
-    public void testWrapNormalTccBean(Object bean, String beanName, Object cacheKey){
+    @ParameterizedTest
+    @MethodSource("normalTccBeanProvider")
+    public void testWrapNormalTccBean(Object bean, String beanName, Object cacheKey) {
         Object result = globalTransactionScanner.wrapIfNecessary(bean, beanName, cacheKey);
-        Assert.assertSame(result, bean);
+        Assertions.assertSame(result, bean);
     }
 
     /**
      * wrapped
      *
-     * @param bean the bean
+     * @param bean     the bean
      * @param beanName the bean name
      * @param cacheKey the cache key
      */
-    @Test(dataProvider = "localTccBeanProvider")
-    public void testWrapLocalTccBean(Object bean, String beanName, Object cacheKey){
+    @ParameterizedTest
+    @MethodSource("localTccBeanProvider")
+    public void testWrapLocalTccBean(Object bean, String beanName, Object cacheKey) {
         TccAction result = (LocalTccAction) globalTransactionScanner.wrapIfNecessary(bean, beanName, cacheKey);
-        Assert.assertNotSame(result, bean);
+        Assertions.assertNotSame(result, bean);
     }
 
     /**
@@ -84,12 +91,13 @@ public class GlobalTransactionScannerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] normalBeanProvider() {
+    static Stream<Arguments> normalBeanProvider() {
         Business business = new BusinessImpl();
         String beanName = "business";
         String cacheKey = "business-key";
-        return new Object[][]{{business, beanName, cacheKey}};
+        return Stream.of(
+                Arguments.of(business, beanName, cacheKey)
+        );
     }
 
     /**
@@ -97,12 +105,13 @@ public class GlobalTransactionScannerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] normalTccBeanProvider() {
+    static Stream<Arguments> normalTccBeanProvider() {
         TccAction tccAction = new TccActionImpl();
         String beanName = "tccBean";
         String cacheKey = "tccBean-key";
-        return new Object[][]{{tccAction, beanName, cacheKey}};
+        return Stream.of(
+                Arguments.of(tccAction, beanName, cacheKey)
+        );
     }
 
     /**
@@ -110,11 +119,12 @@ public class GlobalTransactionScannerTest {
      *
      * @return the object [ ] [ ]
      */
-    @DataProvider
-    public static Object[][] localTccBeanProvider() {
+    static Stream<Arguments> localTccBeanProvider() {
         LocalTccAction localTccAction = new LocalTccActionImpl();
         String beanName = "lcoalTccBean";
         String cacheKey = "lcoalTccBean-key";
-        return new Object[][]{{localTccAction, beanName, cacheKey}};
+        return Stream.of(
+                Arguments.of(localTccAction, beanName, cacheKey)
+        );
     }
 }
diff --git a/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java b/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java
index f6cae98ef9e2d88e66735ef7c873a24454933ab6..76e2eaa5e0805723adb158d3bd54ca67089c3c05 100644
--- a/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java
+++ b/spring/src/test/java/io/seata/spring/annotation/MethodDescTest.java
@@ -18,7 +18,7 @@ package io.seata.spring.annotation;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
diff --git a/style/feats_checkstyle.xml b/style/feats_checkstyle.xml
index d74d820de75224c456c30acdeaaf68261efb6153..806197f083ca2e277ee2f482b7f2c164fd72c282 100644
--- a/style/feats_checkstyle.xml
+++ b/style/feats_checkstyle.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/style/feats_codeStyle.xml b/style/feats_codeStyle.xml
index 228820c510fc0ce55642beae65bc0c6bb748d49e..ff8a90c62a00b75c7edffef727114078eefcc7b0 100644
--- a/style/feats_codeStyle.xml
+++ b/style/feats_codeStyle.xml
@@ -1,5 +1,5 @@
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
diff --git a/tcc/pom.xml b/tcc/pom.xml
index d30618e350f355b6e35f2d205aaf785c7056f8ba..c53552d2ec724051953f103a8c33c8813133bb18 100644
--- a/tcc/pom.xml
+++ b/tcc/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -32,16 +32,12 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-core</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-rm</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 
diff --git a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java b/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java
index 25035727f22848800adec4b6dfb575fb5fcee1ea..ec4e24cbad0eef6f209ad761b684e278c2317417 100644
--- a/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java
+++ b/tcc/src/main/java/io/seata/rm/tcc/api/BusinessActionContext.java
@@ -43,12 +43,12 @@ public class BusinessActionContext implements Serializable {
      * Instantiates a new Business action context.
      *
      * @param xid           the xid
-     * @param actionName    the action name
+     * @param branchId      the branch id
      * @param actionContext the action context
      */
-    public BusinessActionContext(String xid, String actionName, Map<String, Object> actionContext) {
+    public BusinessActionContext(String xid, String branchId, Map<String, Object> actionContext) {
         this.xid = xid;
-        this.actionName = actionName;
+        this.branchId = branchId;
         this.setActionContext(actionContext);
     }
 
diff --git a/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java b/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java
index df234b3c3a922815e225f8a2bb1199b6630f10c7..e11f34fdd2a887b3e79da3d2f736eee375aaa5b2 100644
--- a/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java
+++ b/tcc/src/test/java/io/seata/rm/tcc/interceptor/ActionInterceptorHandlerTest.java
@@ -18,8 +18,8 @@ package io.seata.rm.tcc.interceptor;
 import io.seata.rm.tcc.TccAction;
 import io.seata.rm.tcc.TccParam;
 import io.seata.rm.tcc.api.BusinessActionContext;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -55,9 +55,9 @@ public class ActionInterceptorHandlerTest {
                 new Object[]{null, 10, list, tccParam});
         System.out.println(paramContext);
 
-        Assert.assertEquals(10, paramContext.get("a"));
-        Assert.assertEquals("b", paramContext.get("b"));
-        Assert.assertEquals("abc@ali.com", paramContext.get("email"));
+        Assertions.assertEquals(10, paramContext.get("a"));
+        Assertions.assertEquals("b", paramContext.get("b"));
+        Assertions.assertEquals("abc@ali.com", paramContext.get("email"));
     }
 
-}
\ No newline at end of file
+}
diff --git a/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java b/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java
index dda8f6f59b46270d3cdd81b25a2eacdd6128cdb5..e3cd8ee5dd1980fb9eea9fca442fa45805b5b4fd 100644
--- a/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java
+++ b/tcc/src/test/java/io/seata/rm/tcc/remoting/parser/LocalTCCRemotingParserTest.java
@@ -18,8 +18,8 @@ package io.seata.rm.tcc.remoting.parser;
 import io.seata.rm.tcc.TccAction;
 import io.seata.rm.tcc.TccActionImpl;
 import io.seata.rm.tcc.remoting.RemotingDesc;
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 
 /**
@@ -42,7 +42,7 @@ public class LocalTCCRemotingParserTest {
         TccActionImpl tccAction = new TccActionImpl();
 
         boolean result = localTCCRemotingParser.isService(tccAction, "a");
-        Assert.assertTrue(result);
+        Assertions.assertTrue(result);
     }
 
     /**
@@ -53,7 +53,7 @@ public class LocalTCCRemotingParserTest {
         TccActionImpl tccAction = new TccActionImpl();
 
         boolean result = localTCCRemotingParser.isReference(tccAction, "b");
-        Assert.assertTrue(result);
+        Assertions.assertTrue(result);
     }
 
     /**
@@ -64,11 +64,11 @@ public class LocalTCCRemotingParserTest {
         TccActionImpl tccAction = new TccActionImpl();
 
         RemotingDesc remotingDesc = localTCCRemotingParser.getServiceDesc(tccAction, "c");
-        Assert.assertNotNull(remotingDesc);
+        Assertions.assertNotNull(remotingDesc);
 
-        Assert.assertEquals(remotingDesc.getInterfaceClassName(), "io.seata.rm.tcc.TccAction");
-        Assert.assertEquals(remotingDesc.getInterfaceClass(), TccAction.class);
-        Assert.assertEquals(remotingDesc.getTargetBean(), tccAction);
+        Assertions.assertEquals(remotingDesc.getInterfaceClassName(), "io.seata.rm.tcc.TccAction");
+        Assertions.assertEquals(remotingDesc.getInterfaceClass(), TccAction.class);
+        Assertions.assertEquals(remotingDesc.getTargetBean(), tccAction);
     }
 
-}
\ No newline at end of file
+}
diff --git a/test/pom.xml b/test/pom.xml
index dad41e96bdc8c4c891bfaf460876bb234d006d3d..bdeb1414c1d7ca1a98b7228265b7ed8bf6d6e5f5 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -27,6 +27,13 @@
     <packaging>jar</packaging>
     <name>seata-test ${project.version}</name>
 
+    <properties>
+        <mysql-connector-java.version>5.1.35</mysql-connector-java.version>
+        <zookeeper.version>3.4.8</zookeeper.version>
+        <jedis.version>2.9.0</jedis.version>
+        <redisson.version>3.9.0</redisson.version>
+    </properties>
+
     <build>
         <plugins>
             <plugin>
@@ -48,14 +55,17 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-tm</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-server</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-rm-datasource</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
@@ -64,46 +74,38 @@
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-core</artifactId>
-            <version>4.3.18.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context</artifactId>
-            <version>4.3.18.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context-support</artifactId>
-            <version>4.3.18.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-jdbc</artifactId>
-            <version>4.3.18.RELEASE</version>
         </dependency>
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
-            <version>5.1.35</version>
+            <version>${mysql-connector-java.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.zookeeper</groupId>
             <artifactId>zookeeper</artifactId>
-            <version>3.4.8</version>
+            <version>${zookeeper.version}</version>
         </dependency>
         <dependency>
             <groupId>redis.clients</groupId>
             <artifactId>jedis</artifactId>
-            <version>2.9.0</version>
+            <version>${jedis.version}</version>
         </dependency>
         <dependency>
             <groupId>org.redisson</groupId>
             <artifactId>redisson</artifactId>
-            <version>3.9.0</version>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
+            <version>${redisson.version}</version>
         </dependency>
 
     </dependencies>
diff --git a/test/src/main/java/io/seata/test/DataSourceBasicTest.java b/test/src/main/java/io/seata/test/DataSourceBasicTest.java
deleted file mode 100644
index a323c1db43a21f21145045e625d623ab34a8013b..0000000000000000000000000000000000000000
--- a/test/src/main/java/io/seata/test/DataSourceBasicTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *  Copyright 1999-2019 Seata.io Group.
- *
- *  Licensed 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 io.seata.test;
-
-import java.util.Date;
-import java.util.concurrent.atomic.AtomicLong;
-
-import io.seata.core.context.RootContext;
-import io.seata.core.exception.TransactionException;
-import io.seata.core.model.BranchStatus;
-import io.seata.core.model.BranchType;
-import io.seata.rm.DefaultResourceManager;
-import io.seata.rm.RMClient;
-import io.seata.rm.datasource.DataSourceManager;
-import io.seata.tm.TMClient;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.jdbc.core.JdbcTemplate;
-
-/**
- * The type Data source basic test.
- *
- * @author sharajava
- */
-@Ignore
-public class DataSourceBasicTest {
-
-    private static ClassPathXmlApplicationContext context;
-    private static JdbcTemplate jdbcTemplate;
-    private static JdbcTemplate directJdbcTemplate;
-
-    private static final String APPLICATION_ID = "my_test_app";
-    private static final String TX_SERVICE_GROUP = "my_test_tx_group";
-    private static final long GID = 12345678L;
-    private static final AtomicLong INC_LONG = new AtomicLong(1);
-
-    private static void initClient() {
-        TMClient.init(APPLICATION_ID, TX_SERVICE_GROUP);
-        RMClient.init(APPLICATION_ID, TX_SERVICE_GROUP);
-    }
-
-    /**
-     * Before.
-     */
-    @BeforeClass
-    public static void before() {
-        initClient();
-        // Mock DataSourceManager
-        DefaultResourceManager.mockResourceManager(BranchType.AT, new DataSourceManager() {
-
-            @Override
-            public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid,
-                                       String applicationData, String lockKeys) throws TransactionException {
-                return GID + INC_LONG.incrementAndGet();
-            }
-
-            @Override
-            public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status,
-                                     String applicationData) {
-
-            }
-
-            @Override
-            public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) {
-                return true;
-            }
-
-            @Override
-            public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId,
-                                             String applicationData) {
-                return BranchStatus.PhaseTwo_Committed;
-            }
-
-            @Override
-            public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId,
-                                               String applicationData) {
-                return BranchStatus.PhaseTwo_Rollbacked;
-            }
-        });
-
-        context = new ClassPathXmlApplicationContext(
-            "basic-test-context.xml");
-        jdbcTemplate = (JdbcTemplate)context
-            .getBean("jdbcTemplate");
-        directJdbcTemplate = (JdbcTemplate)context
-            .getBean("directJdbcTemplate");
-        RootContext.bind("127.0.0.1:8091:" + GID);
-        directJdbcTemplate.update("delete from undo_log");
-
-    }
-
-    /**
-     * After.
-     */
-    @AfterClass
-    public static void after() {
-        RootContext.unbind();
-        if (context != null) {
-            context.close();
-        }
-    }
-
-    /**
-     * Test update.
-     */
-    @Test
-    public void testUpdate() {
-        jdbcTemplate.update("update user0 a set a.name = 'yyyy' where a.id = ?", new Object[] {1});
-    }
-
-    /**
-     * Test update with alias.
-     */
-    @Test
-    public void testUpdateWithAlias() {
-        jdbcTemplate.update("update user0 a set a.name = 'yyyy' where a.name = ?", new Object[] {"yyyy"});
-    }
-
-    /**
-     * Test delete.
-     */
-    @Test
-    public void testDelete() {
-        jdbcTemplate.update("delete from user0 where id = ?", new Object[] {2});
-    }
-
-    /**
-     * Test select for update.
-     */
-    @Test
-    public void testSelectForUpdate() {
-        jdbcTemplate.queryForRowSet("select a.name from user0 a where a.id = ? for update", new Object[] {1});
-    }
-
-    /**
-     * Test select for update with alias.
-     */
-    @Test
-    public void testSelectForUpdateWithAlias() {
-        jdbcTemplate.queryForRowSet("select a.name from user0 a where a.id = ? for update", new Object[] {1});
-    }
-
-    /**
-     * Test insert.
-     */
-    @Test
-    public void testInsert() {
-        directJdbcTemplate.update("delete from user0 where id = ?",
-            new Object[] {2});
-        jdbcTemplate.update("insert into user0 (id, name, gmt) values (?, ?, ?)",
-            new Object[] {2, "xxx", new Date()});
-    }
-
-    /**
-     * Test update with alias 1.
-     */
-    @Test
-    public void testUpdateWithAlias1() {
-
-        directJdbcTemplate.update("delete from user1 where Id = ?",
-            new Object[] {1});
-        directJdbcTemplate.update("insert into user1 (Id, Name, gMt) values (?, ?, ?)",
-            new Object[] {1, "xxx", new Date()});
-        jdbcTemplate.update("update user1 a set a.Name = 'yyy' where a.Name = ?", new Object[] {"xxx"});
-    }
-}
diff --git a/test/src/main/java/io/seata/test/client/AppTest.java b/test/src/test/java/AppTest.java
similarity index 89%
rename from test/src/main/java/io/seata/test/client/AppTest.java
rename to test/src/test/java/AppTest.java
index 0795ec268e83a10cbeb643c187af056514e6549f..e20c6cb00ce4a2cca8ce7da420216e1fd13bbd9e 100644
--- a/test/src/main/java/io/seata/test/client/AppTest.java
+++ b/test/src/test/java/AppTest.java
@@ -13,16 +13,13 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package io.seata.test.client;
-
+import io.seata.common.ApplicationKeeper;
 import io.seata.rm.RMClient;
-import io.seata.test.common.ApplicationKeeper;
 import io.seata.tm.TMClient;
 import io.seata.tm.api.TransactionalExecutor;
 import io.seata.tm.api.TransactionalTemplate;
-
 import io.seata.tm.api.transaction.TransactionInfo;
-import org.junit.Assert;
+import org.junit.jupiter.api.Assertions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -52,10 +49,10 @@ public class AppTest {
         RMClient.init(APPLICATION_ID, TX_SERVICE_GROUP);
 
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
-            "basic-test-context.xml");
+                "basic-test-context.xml");
 
-        final JdbcTemplate jdbcTemplate = (JdbcTemplate)context
-            .getBean("jdbcTemplate");
+        final JdbcTemplate jdbcTemplate = (JdbcTemplate) context
+                .getBean("jdbcTemplate");
 
         jdbcTemplate.update("delete from undo_log");
         jdbcTemplate.update("delete from user0");
@@ -70,7 +67,7 @@ public class AppTest {
                     if (LOGGER.isInfoEnabled()) {
                         LOGGER.info("Exception Rollback Business Begin ...");
                     }
-                    jdbcTemplate.update("update user0 set name = 'xxx' where id = ?", new Object[] {1});
+                    jdbcTemplate.update("update user0 set name = 'xxx' where id = ?", new Object[]{1});
                     jdbcTemplate.update("insert into user1 (id, name, gmt) values (1, 'user1', '2019-01-01')");
                     throw bizException;
                 }
@@ -89,11 +86,11 @@ public class AppTest {
             if (code == TransactionalExecutor.Code.RollbackDone) {
                 Throwable businessEx = e.getOriginalException();
                 if (businessEx instanceof MyBusinessException) {
-                    Assert.assertEquals(((MyBusinessException)businessEx).getBusinessErrorCode(),
-                        bizException.businessErrorCode);
+                    Assertions.assertEquals(((MyBusinessException) businessEx).getBusinessErrorCode(),
+                            bizException.businessErrorCode);
                 }
             } else {
-                Assert.assertFalse("Not expected," + e.getMessage(), false);
+                Assertions.assertFalse(false, "Not expected," + e.getMessage());
 
             }
         }
diff --git a/test/src/main/java/io/seata/test/LocalTransactionWithGlobalLockDataSourceBasicTest.java b/test/src/test/java/LocalTransactionWithGlobalLockDataSourceBasicTest.java
similarity index 84%
rename from test/src/main/java/io/seata/test/LocalTransactionWithGlobalLockDataSourceBasicTest.java
rename to test/src/test/java/LocalTransactionWithGlobalLockDataSourceBasicTest.java
index a1dfdbeac410ecd0fa6ada9f273ced2031fccc9a..1e851ff683f25d53eea1c24c63884929c42c6bd7 100644
--- a/test/src/main/java/io/seata/test/LocalTransactionWithGlobalLockDataSourceBasicTest.java
+++ b/test/src/test/java/LocalTransactionWithGlobalLockDataSourceBasicTest.java
@@ -13,10 +13,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package io.seata.test;
-
-import java.util.Date;
-
 import io.seata.core.context.RootContext;
 import io.seata.core.exception.TransactionException;
 import io.seata.core.model.BranchStatus;
@@ -26,22 +22,23 @@ import io.seata.rm.DefaultResourceManager;
 import io.seata.rm.RMClient;
 import io.seata.rm.datasource.DataSourceManager;
 import io.seata.tm.TMClient;
-
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.jdbc.UncategorizedSQLException;
 import org.springframework.jdbc.core.JdbcTemplate;
 
+import java.util.Date;
+
 /**
  * The type Data source basic test.
  *
  * @author services
  */
-@Ignore
+@Disabled
 public class LocalTransactionWithGlobalLockDataSourceBasicTest {
 
     private static ClassPathXmlApplicationContext context;
@@ -53,17 +50,17 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     /**
      * Before.
      */
-    @BeforeClass
+    @BeforeAll
     public static void before() {
         // Mock DataSourceManager
         initClient();
         DefaultResourceManager.mockResourceManager(BranchType.AT, new MockDataSourceManager());
         context = new ClassPathXmlApplicationContext(
-            "basic-test-context.xml");
-        jdbcTemplate = (JdbcTemplate)context
-            .getBean("jdbcTemplate");
-        directJdbcTemplate = (JdbcTemplate)context
-            .getBean("directJdbcTemplate");
+                "basic-test-context.xml");
+        jdbcTemplate = (JdbcTemplate) context
+                .getBean("jdbcTemplate");
+        directJdbcTemplate = (JdbcTemplate) context
+                .getBean("directJdbcTemplate");
 
         directJdbcTemplate.execute("delete from user0");
         directJdbcTemplate.execute("delete from user1");
@@ -77,7 +74,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     public void testInsert() {
         RootContext.bindGlobalLockFlag();
         jdbcTemplate.update("insert into user0 (id, name, gmt) values (?, ?, ?)",
-            new Object[] {2, "xxx", new Date()});
+                new Object[]{2, "xxx", new Date()});
     }
 
     /**
@@ -90,7 +87,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
             @Override
             public void doExecute() {
                 jdbcTemplate.update("insert into user0 (id, name, gmt) values (?, ?, ?)",
-                    new Object[] {3, "xxx", new Date()});
+                        new Object[]{3, "xxx", new Date()});
             }
         }.execute();
     }
@@ -101,7 +98,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     @Test
     public void testUpdate() {
         RootContext.bindGlobalLockFlag();
-        jdbcTemplate.update("update user0 a set a.name = 'yyyy' where a.id = ?", new Object[] {1});
+        jdbcTemplate.update("update user0 a set a.name = 'yyyy' where a.id = ?", new Object[]{1});
     }
 
     @Test
@@ -111,7 +108,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
         new AbstractLockConflictExecuteTemplate() {
             @Override
             public void doExecute() {
-                jdbcTemplate.update("update user0 a set a.name = 'yyyy' where a.id = ?", new Object[] {1});
+                jdbcTemplate.update("update user0 a set a.name = 'yyyy' where a.id = ?", new Object[]{1});
 
             }
         }.execute();
@@ -124,28 +121,28 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     public void testUpdateWithAlias1() {
 
         directJdbcTemplate.update("delete from User1 where Id = ?",
-            new Object[] {1});
+                new Object[]{1});
         directJdbcTemplate.update("insert into User1 (Id, Name, gMt) values (?, ?, ?)",
-            new Object[] {1, "xxx", new Date()});
+                new Object[]{1, "xxx", new Date()});
 
         RootContext.bindGlobalLockFlag();
-        jdbcTemplate.update("update User1 a set a.Name = 'yyy' where a.Name = ?", new Object[] {"xxx"});
+        jdbcTemplate.update("update User1 a set a.Name = 'yyy' where a.Name = ?", new Object[]{"xxx"});
     }
 
     @Test
     public void testUpdateWithAlias1WithLockConflict() {
 
         directJdbcTemplate.update("delete from User1 where Id = ?",
-            new Object[] {1});
+                new Object[]{1});
         directJdbcTemplate.update("insert into User1 (Id, Name, gMt) values (?, ?, ?)",
-            new Object[] {1, "xxx", new Date()});
+                new Object[]{1, "xxx", new Date()});
 
         RootContext.bindGlobalLockFlag();
         new AbstractLockConflictExecuteTemplate() {
 
             @Override
             public void doExecute() {
-                jdbcTemplate.update("update User1 a set a.Name = 'yyy' where a.Name = ?", new Object[] {"xxx"});
+                jdbcTemplate.update("update User1 a set a.Name = 'yyy' where a.Name = ?", new Object[]{"xxx"});
             }
         };
 
@@ -157,7 +154,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     @Test
     public void testDelete() {
         RootContext.bindGlobalLockFlag();
-        jdbcTemplate.update("delete from user0 where id = ?", new Object[] {2});
+        jdbcTemplate.update("delete from user0 where id = ?", new Object[]{2});
     }
 
     /**
@@ -170,7 +167,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
 
             @Override
             public void doExecute() {
-                jdbcTemplate.update("delete from user0 where id = ?", new Object[] {2});
+                jdbcTemplate.update("delete from user0 where id = ?", new Object[]{2});
             }
         };
     }
@@ -181,7 +178,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     @Test
     public void testSelectForUpdate() {
         RootContext.bindGlobalLockFlag();
-        jdbcTemplate.queryForRowSet("select a.name from user0 a where a.id = ? for update", new Object[] {1});
+        jdbcTemplate.queryForRowSet("select a.name from user0 a where a.id = ? for update", new Object[]{1});
     }
 
     /**
@@ -194,7 +191,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
 
             @Override
             public void doExecute() {
-                jdbcTemplate.queryForRowSet("select a.name from user0 a where a.id = ? for update", new Object[] {1});
+                jdbcTemplate.queryForRowSet("select a.name from user0 a where a.id = ? for update", new Object[]{1});
             }
         };
     }
@@ -214,7 +211,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
 
         @Override
         public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
-            throws TransactionException {
+                throws TransactionException {
             return true;
         }
 
@@ -235,7 +232,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
 
         @Override
         public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData)
-            throws TransactionException {
+                throws TransactionException {
             throw new RuntimeException("this method should not be called!");
         }
     }
@@ -251,7 +248,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
                 DefaultResourceManager.mockResourceManager(BranchType.AT, new MockDataSourceManager() {
                     @Override
                     public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
-                        throws TransactionException {
+                            throws TransactionException {
                         return false;
                     }
                 });
@@ -261,12 +258,12 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
                     doExecute();
                 } catch (UncategorizedSQLException e) {
                     exceptionOccour = true;
-                    Assert.assertTrue("not lock Conflict exception", e.getMessage().contains("LockConflict"));
+                    Assertions.assertTrue(e.getMessage().contains("LockConflict"), "not lock Conflict exception");
                 } finally {
                     DefaultResourceManager.mockResourceManager(BranchType.AT, new MockDataSourceManager());
                 }
 
-                Assert.assertTrue("Lock Exception not occur!", exceptionOccour);
+                Assertions.assertTrue(exceptionOccour, "Lock Exception not occur!");
             }
         }
 
@@ -277,7 +274,7 @@ public class LocalTransactionWithGlobalLockDataSourceBasicTest {
     /**
      * After.
      */
-    @AfterClass
+    @AfterAll
     public static void after() {
         if (context != null) {
             context.close();
diff --git a/test/src/main/java/io/seata/test/common/ApplicationKeeper.java b/test/src/test/java/io/seata/common/ApplicationKeeper.java
similarity index 96%
rename from test/src/main/java/io/seata/test/common/ApplicationKeeper.java
rename to test/src/test/java/io/seata/common/ApplicationKeeper.java
index 0bbdf7fdce682d2f69d76663bdff859932bf9836..77af0d9bdda7ecc98f38c3dfaab3af67be793699 100644
--- a/test/src/main/java/io/seata/test/common/ApplicationKeeper.java
+++ b/test/src/test/java/io/seata/common/ApplicationKeeper.java
@@ -13,7 +13,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package io.seata.test.common;
+package io.seata.common;
 
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
@@ -73,7 +73,7 @@ public class ApplicationKeeper {
                 LOGGER.info("Application is keep running ... ");
                 LOCK.wait();
             } catch (InterruptedException e) {
-                e.printStackTrace();
+                LOGGER.error("interrupted error", e);
             }
         }
     }
diff --git a/test/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java b/test/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java
index b5b4c1a39a410094f7f6fadf529e796d488b7bea..45b8638c2180f846dd18de154766333412aee275 100644
--- a/test/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java
+++ b/test/src/test/java/io/seata/common/loader/EnhancedServiceLoaderTest.java
@@ -15,8 +15,8 @@
  */
 package io.seata.common.loader;
 
-import org.junit.Assert;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 import java.util.List;
 
@@ -30,13 +30,13 @@ public class EnhancedServiceLoaderTest {
     public void testLoadBeanByOrder(){
         LoaderTestSPI loader  = EnhancedServiceLoader.load(LoaderTestSPI.class, EnhancedServiceLoaderTest.class.getClassLoader());
         System.out.println(loader.echo());
-        Assert.assertEquals("impl_2", loader.echo());
+        Assertions.assertEquals("impl_2", loader.echo());
     }
 
     @Test
     public void testLoadAll(){
         List<LoaderTestSPI> list = EnhancedServiceLoader.loadAll(LoaderTestSPI.class);
-        Assert.assertEquals(2, list.size());
+        Assertions.assertEquals(2, list.size());
     }
 
 
diff --git a/test/src/main/java/io/seata/common/loader/LoaderTestImpl1.java b/test/src/test/java/io/seata/common/loader/LoaderTestImpl1.java
similarity index 100%
rename from test/src/main/java/io/seata/common/loader/LoaderTestImpl1.java
rename to test/src/test/java/io/seata/common/loader/LoaderTestImpl1.java
diff --git a/test/src/main/java/io/seata/common/loader/LoaderTestImpl2.java b/test/src/test/java/io/seata/common/loader/LoaderTestImpl2.java
similarity index 100%
rename from test/src/main/java/io/seata/common/loader/LoaderTestImpl2.java
rename to test/src/test/java/io/seata/common/loader/LoaderTestImpl2.java
diff --git a/test/src/main/java/io/seata/common/loader/LoaderTestSPI.java b/test/src/test/java/io/seata/common/loader/LoaderTestSPI.java
similarity index 100%
rename from test/src/main/java/io/seata/common/loader/LoaderTestSPI.java
rename to test/src/test/java/io/seata/common/loader/LoaderTestSPI.java
diff --git a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java b/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java
index 7d07262cbd4b126454c5bfe8f252d8cf18c6e034..dc5682b9b10f6ee89d182b0d85f97ee162bfb0a3 100644
--- a/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java
+++ b/test/src/test/java/io/seata/core/rpc/netty/TmRpcClientTest.java
@@ -30,15 +30,15 @@ import io.netty.channel.Channel;
 import io.seata.core.protocol.ResultCode;
 import io.seata.core.protocol.transaction.BranchRegisterRequest;
 import io.seata.core.protocol.transaction.BranchRegisterResponse;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author jimin.jm@alibaba-inc.com
  * @date 2019/01/25
  */
-@Ignore
+@Disabled
 public class TmRpcClientTest {
 
     private static final ThreadPoolExecutor
@@ -77,7 +77,7 @@ public class TmRpcClientTest {
         doConnectMethod.setAccessible(true);
         String serverAddress = "0.0.0.0:8091";
         Channel channel = (Channel) doConnectMethod.invoke(tmRpcClient, serverAddress);
-        Assert.assertNotNull(channel);
+        Assertions.assertNotNull(channel);
     }
 
     /**
@@ -135,16 +135,16 @@ public class TmRpcClientTest {
         doConnectMethod.setAccessible(true);
         String serverAddress = "0.0.0.0:8091";
         Channel channel = (Channel) doConnectMethod.invoke(tmRpcClient, serverAddress);
-        Assert.assertNotNull(channel);
+        Assertions.assertNotNull(channel);
 
         BranchRegisterRequest request = new BranchRegisterRequest();
         request.setXid("127.0.0.1:8091:1249853");
         request.setLockKey("lock key testSendMsgWithResponse");
         request.setResourceId("resoutceId1");
         BranchRegisterResponse branchRegisterResponse = (BranchRegisterResponse)tmRpcClient.sendMsgWithResponse(request);
-        Assert.assertNotNull(branchRegisterResponse);
-        Assert.assertEquals(ResultCode.Failed, branchRegisterResponse.getResultCode());
-        Assert.assertEquals("RuntimeException[SessionManager is NOT init!]",
+        Assertions.assertNotNull(branchRegisterResponse);
+        Assertions.assertEquals(ResultCode.Failed, branchRegisterResponse.getResultCode());
+        Assertions.assertEquals("RuntimeException[SessionManager is NOT init!]",
                             branchRegisterResponse.getMsg());
     }
 }
diff --git a/test/src/main/resources/META-INF/services/io.seata.common.loader.LoaderTestSPI b/test/src/test/resources/META-INF/services/io.seata.common.loader.LoaderTestSPI
similarity index 100%
rename from test/src/main/resources/META-INF/services/io.seata.common.loader.LoaderTestSPI
rename to test/src/test/resources/META-INF/services/io.seata.common.loader.LoaderTestSPI
diff --git a/test/src/main/resources/basic-test-context.xml b/test/src/test/resources/basic-test-context.xml
similarity index 95%
rename from test/src/main/resources/basic-test-context.xml
rename to test/src/test/resources/basic-test-context.xml
index 8e71203639b65f80f7187621a5183742eafa119b..a41f78bfa40c695fb7a2116ab799bff35199cecd 100644
--- a/test/src/main/resources/basic-test-context.xml
+++ b/test/src/test/resources/basic-test-context.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -50,5 +50,5 @@
 		<property name="dataSource" ref="mysqlDataSource" />
 	</bean>
 
-    <bean id="clientTest" class="io.seata.test.DataSourceBasicTest"/>
+    <bean id="clientTest" class="DataSourceBasicTest"/>
 </beans>
diff --git a/test/src/main/resources/biz.sql b/test/src/test/resources/biz.sql
similarity index 100%
rename from test/src/main/resources/biz.sql
rename to test/src/test/resources/biz.sql
diff --git a/test/src/main/resources/file.conf b/test/src/test/resources/file.conf
similarity index 100%
rename from test/src/main/resources/file.conf
rename to test/src/test/resources/file.conf
diff --git a/test/src/main/resources/logback.xml b/test/src/test/resources/logback.xml
similarity index 90%
rename from test/src/main/resources/logback.xml
rename to test/src/test/resources/logback.xml
index 50bbdb2e4b6043fe96c6f773d3ea1ba5d12ac2f9..1d6742f34c746287e13495d36d15de19eb259a70 100755
--- a/test/src/main/resources/logback.xml
+++ b/test/src/test/resources/logback.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
   -->
 
 <configuration>
-	<!-- 控制台输出日志 -->
+	<!-- Console output log -->
 	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 		<layout class="ch.qos.logback.classic.PatternLayout">
 			<Pattern>%date [SEATA] [%thread] %-5level %logger{80} - %msg%n</Pattern>
@@ -26,4 +26,4 @@
 	<root level="DEBUG">
 		<appender-ref ref="STDOUT" />
 	</root>
-</configuration> 
+</configuration>
diff --git a/test/src/main/resources/registry.conf b/test/src/test/resources/registry.conf
similarity index 93%
rename from test/src/main/resources/registry.conf
rename to test/src/test/resources/registry.conf
index 15677236a892397e6babed5c83f1263b842a56c2..1cddea7219444a8f50ee5bdc7f7170de40884356 100644
--- a/test/src/main/resources/registry.conf
+++ b/test/src/test/resources/registry.conf
@@ -45,7 +45,7 @@ registry {
 }
 
 config {
-  # file、nacos 、apollo、zk
+  # file、nacos 、apollo、zk、consul
   type = "file"
 
   nacos {
@@ -53,6 +53,9 @@ config {
     namespace = "public"
     cluster = "default"
   }
+  consul {
+    serverAddr = "127.0.0.1:8500"
+  }
   apollo {
     app.id = "seata-server"
     apollo.meta = "http://192.168.1.204:8801"
diff --git a/tm/pom.xml b/tm/pom.xml
index f538900c92b340e515498df8c285fe571f9f012a..51ecd9ea561efa09993be10269b585a0580ff5ef 100644
--- a/tm/pom.xml
+++ b/tm/pom.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  ~  Copyright 1999-2018 Alibaba Group Holding Ltd.
+  ~  Copyright 1999-2019 Seata.io Group.
   ~
   ~  Licensed under the Apache License, Version 2.0 (the "License");
   ~  you may not use this file except in compliance with the License.
@@ -32,11 +32,7 @@
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>seata-core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
+            <version>${project.version}</version>
         </dependency>
     </dependencies>
 
diff --git a/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java b/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java
index d98c4e1978437602b11199fa0710a039e9cbcdeb..92f713052a173c8987ff65f59c3e28264783e022 100644
--- a/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java
+++ b/tm/src/main/java/io/seata/tm/api/DefaultFailureHandlerImpl.java
@@ -15,9 +15,17 @@
  */
 package io.seata.tm.api;
 
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
+import io.seata.common.thread.NamedThreadFactory;
+import io.seata.core.exception.TransactionException;
+import io.seata.core.model.GlobalStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * The type Default failure handler.
  *
@@ -25,8 +33,24 @@ import org.slf4j.LoggerFactory;
  * @date 2019 /1/8
  */
 public class DefaultFailureHandlerImpl implements FailureHandler {
+
     private static final Logger LOGGER = LoggerFactory.getLogger(DefaultFailureHandlerImpl.class);
 
+    /**
+     * Retry 1 hours by default
+     */
+    private static final int RETRY_MAX_TIMES = 6 * 60;
+
+    private static final long SCHEDULE_INTERVAL_SECONDS = 10;
+
+    private static final long TICK_DURATION = 1;
+
+    private static final int TICKS_PER_WHEEL = 8;
+
+    private HashedWheelTimer timer = new HashedWheelTimer(
+            new NamedThreadFactory("failedTransactionRetry",1),
+            TICK_DURATION, TimeUnit.SECONDS, TICKS_PER_WHEEL);
+
     @Override
     public void onBeginFailure(GlobalTransaction tx, Throwable cause) {
         LOGGER.warn("Failed to begin transaction. ", cause);
@@ -35,10 +59,54 @@ public class DefaultFailureHandlerImpl implements FailureHandler {
     @Override
     public void onCommitFailure(GlobalTransaction tx, Throwable cause) {
         LOGGER.warn("Failed to commit transaction[" + tx.getXid() + "]", cause);
+        timer.newTimeout(new CheckTimerTask(tx, GlobalStatus.Committed), SCHEDULE_INTERVAL_SECONDS, TimeUnit.SECONDS);
     }
 
     @Override
     public void onRollbackFailure(GlobalTransaction tx, Throwable cause) {
         LOGGER.warn("Failed to rollback transaction[" + tx.getXid() + "]", cause);
+        timer.newTimeout(new CheckTimerTask(tx, GlobalStatus.Rollbacked), SCHEDULE_INTERVAL_SECONDS, TimeUnit.SECONDS);
+    }
+
+    protected class CheckTimerTask implements TimerTask{
+
+        private final GlobalTransaction tx;
+
+        private final GlobalStatus required;
+
+        private int count = 0;
+
+        private boolean isStopped = false;
+
+        protected CheckTimerTask(final GlobalTransaction tx, GlobalStatus required) {
+            this.tx = tx;
+            this.required = required;
+        }
+
+        @Override
+        public void run(Timeout timeout) throws Exception {
+            if(!isStopped){
+                if(++count > RETRY_MAX_TIMES){
+                    LOGGER.error("transaction[" + tx.getXid() + "] retry fetch status times exceed the limit [" + RETRY_MAX_TIMES + " times]");
+                    return;
+                }
+                isStopped = shouldStop(tx, required);
+                timer.newTimeout(this, SCHEDULE_INTERVAL_SECONDS, TimeUnit.SECONDS);
+            }
+        }
+    }
+
+    private boolean shouldStop(final GlobalTransaction tx, GlobalStatus required){
+        try {
+            GlobalStatus status = tx.getStatus();
+            LOGGER.info("transaction[" + tx.getXid() + "] current status is [" + status + "]");
+            if(status == required || status == GlobalStatus.Finished){
+                return true;
+            }
+        } catch (TransactionException e) {
+            LOGGER.error("fetch GlobalTransaction status error", e);
+        }
+        return false;
     }
+
 }
diff --git a/tm/src/test/java/io/seata/tm/api/APITest.java b/tm/src/test/java/io/seata/tm/api/APITest.java
index c0cbabd77041130f4a4f4685385cde2b4b95a2fe..8b209515eff66b8b6ea10bf4e774b92092dcb85c 100644
--- a/tm/src/test/java/io/seata/tm/api/APITest.java
+++ b/tm/src/test/java/io/seata/tm/api/APITest.java
@@ -19,14 +19,12 @@ import io.seata.core.context.RootContext;
 import io.seata.core.exception.TransactionException;
 import io.seata.core.model.GlobalStatus;
 import io.seata.core.model.TransactionManager;
-import io.seata.tm.DefaultTransactionManager;
-
 import io.seata.tm.TransactionManagerHolder;
 import io.seata.tm.api.transaction.TransactionInfo;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
 
 /**
  * The type Api test.
@@ -40,12 +38,12 @@ public class APITest {
     /**
      * Init.
      */
-    @BeforeClass
+    @BeforeAll
     public static void init() {
         TransactionManagerHolder.set(new TransactionManager() {
             @Override
             public String begin(String applicationId, String transactionServiceGroup, String name, int timeout)
-                throws TransactionException {
+                    throws TransactionException {
                 return DEFAULT_XID;
             }
 
@@ -69,7 +67,7 @@ public class APITest {
     /**
      * Clean root context.
      */
-    @After
+    @AfterEach
     public void cleanRootContext() {
         RootContext.unbind();
     }
@@ -83,8 +81,8 @@ public class APITest {
     public void testCurrent() throws Exception {
         RootContext.bind(DEFAULT_XID);
         GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
-        Assert.assertEquals(tx.getXid(), DEFAULT_XID);
-        Assert.assertEquals(tx.getStatus(), GlobalStatus.Begin);
+        Assertions.assertEquals(tx.getXid(), DEFAULT_XID);
+        Assertions.assertEquals(tx.getStatus(), GlobalStatus.Begin);
 
     }
 
@@ -96,8 +94,8 @@ public class APITest {
     @Test
     public void testNewTx() throws Exception {
         GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
-        Assert.assertEquals(tx.getStatus(), GlobalStatus.UnKnown);
-        Assert.assertNull(tx.getXid());
+        Assertions.assertEquals(tx.getStatus(), GlobalStatus.UnKnown);
+        Assertions.assertNull(tx.getXid());
     }
 
     /**
@@ -109,8 +107,8 @@ public class APITest {
     public void testBegin() throws Exception {
         GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
         tx.begin();
-        Assert.assertEquals(tx.getStatus(), GlobalStatus.Begin);
-        Assert.assertNotNull(tx.getXid());
+        Assertions.assertEquals(tx.getStatus(), GlobalStatus.Begin);
+        Assertions.assertNotNull(tx.getXid());
 
     }
 
@@ -190,7 +188,7 @@ public class APITest {
             });
         } catch (TransactionalExecutor.ExecutionException ex) {
             Throwable oex = ex.getOriginalException();
-            Assert.assertEquals(oex.getMessage(), oexMsg);
+            Assertions.assertEquals(oex.getMessage(), oexMsg);
         }
     }
 
diff --git a/tm/src/test/java/io/seata/tm/api/TransactionTemplateTest.java b/tm/src/test/java/io/seata/tm/api/TransactionTemplateTest.java
index 3f461fb8bf2fd1a87ffb87301827761f725d56f2..17dc2a73f5c21837e67f4a66fc5f3ffb6a52d97e 100644
--- a/tm/src/test/java/io/seata/tm/api/TransactionTemplateTest.java
+++ b/tm/src/test/java/io/seata/tm/api/TransactionTemplateTest.java
@@ -17,16 +17,15 @@ package io.seata.tm.api;
 
 import io.seata.core.model.GlobalStatus;
 import io.seata.core.model.TransactionManager;
-import io.seata.tm.DefaultTransactionManager;
 import io.seata.tm.TransactionManagerHolder;
 import io.seata.tm.api.transaction.NoRollbackRule;
 import io.seata.tm.api.transaction.RollbackRule;
 import io.seata.tm.api.transaction.TransactionHook;
 import io.seata.tm.api.transaction.TransactionHookManager;
 import io.seata.tm.api.transaction.TransactionInfo;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
 import java.util.LinkedHashSet;
@@ -49,7 +48,7 @@ public class TransactionTemplateTest {
 
     private TransactionalExecutor transactionalExecutor;
 
-    @Before
+    @BeforeEach
     public void init() throws Exception {
         // mock transactionManager
         TransactionManager transactionManager = mock(TransactionManager.class);
@@ -67,7 +66,7 @@ public class TransactionTemplateTest {
         when(transactionalExecutor.getTransactionInfo()).thenReturn(txInfo);
     }
 
-    @After
+    @AfterEach
     public void assertHooks() {
         assertThat(TransactionHookManager.getHooks()).isEmpty();
     }
@@ -100,7 +99,7 @@ public class TransactionTemplateTest {
     public void testTransactionRollbackHook_WithRollBackRule() throws Throwable {
         Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
         rollbackRules.add(new RollbackRule(NullPointerException.class));
-        TransactionHook transactionHook = testRollBackRules(rollbackRules,new NullPointerException());
+        TransactionHook transactionHook = testRollBackRules(rollbackRules, new NullPointerException());
         verifyRollBack(transactionHook);
     }
 
@@ -108,7 +107,7 @@ public class TransactionTemplateTest {
     public void testTransactionRollbackHook_WithNoRollBackRule() throws Throwable {
         Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
         rollbackRules.add(new NoRollbackRule(NullPointerException.class));
-        TransactionHook transactionHook = testRollBackRules(rollbackRules,new NullPointerException());
+        TransactionHook transactionHook = testRollBackRules(rollbackRules, new NullPointerException());
         verifyCommit(transactionHook);
     }
 
@@ -117,11 +116,11 @@ public class TransactionTemplateTest {
         Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
         rollbackRules.add(new RollbackRule(NullPointerException.class));
         rollbackRules.add(new NoRollbackRule(NullPointerException.class));
-        TransactionHook transactionHook = testRollBackRules(rollbackRules,new NullPointerException());
+        TransactionHook transactionHook = testRollBackRules(rollbackRules, new NullPointerException());
         verifyRollBack(transactionHook);
     }
 
-    private TransactionHook testRollBackRules(Set<RollbackRule> rollbackRules,Throwable throwable) throws Throwable {
+    private TransactionHook testRollBackRules(Set<RollbackRule> rollbackRules, Throwable throwable) throws Throwable {
         TransactionHook transactionHook = Mockito.mock(TransactionHook.class);
         // mock  txInfo
         TransactionInfo txInfo = new TransactionInfo();
diff --git a/tm/src/test/java/io/seata/tm/api/transaction/RollbackRuleTest.java b/tm/src/test/java/io/seata/tm/api/transaction/RollbackRuleTest.java
index 1c6ef0e9e08eaa81c2ce69e693810a01f3e7ef39..c36d44ca9313f661d78032b3c6a7ac6d27eaa1a1 100644
--- a/tm/src/test/java/io/seata/tm/api/transaction/RollbackRuleTest.java
+++ b/tm/src/test/java/io/seata/tm/api/transaction/RollbackRuleTest.java
@@ -16,11 +16,13 @@
 package io.seata.tm.api.transaction;
 
 import io.seata.common.exception.ShouldNeverHappenException;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
 
 import static org.assertj.core.api.Assertions.assertThat;
+
 /**
  * @author guoyao
  * @date 2019/4/18
@@ -57,23 +59,23 @@ public class RollbackRuleTest {
         RollbackRule rr = new RollbackRule(java.lang.Throwable.class.getName());
         assertThat(rr.getDepth(new MyRuntimeException("")) > 0).isTrue();
         assertThat(rr.getDepth(new IOException()) > 0).isTrue();
-        assertThat(rr.getDepth(new ShouldNeverHappenException(null,null)) > 0).isTrue();
+        assertThat(rr.getDepth(new ShouldNeverHappenException(null, null)) > 0).isTrue();
         assertThat(rr.getDepth(new RuntimeException()) > 0).isTrue();
     }
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test
     public void ctorArgMustBeAThrowableClassWithNonThrowableType() {
-        new RollbackRule(String.class);
+        Assertions.assertThrows(IllegalArgumentException.class, () -> new RollbackRule(String.class));
     }
 
-    @Test(expected = NullPointerException.class)
+    @Test
     public void ctorArgMustBeAThrowableClassWithNullThrowableType() {
-        new RollbackRule((Class<?>) null);
+        Assertions.assertThrows(NullPointerException.class, () -> new RollbackRule((Class<?>) null));
     }
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test
     public void ctorArgExceptionStringNameVersionWithNull() {
-        new RollbackRule((String) null);
+        Assertions.assertThrows(IllegalArgumentException.class, () -> new RollbackRule((String) null));
     }
 
 }
diff --git a/tm/src/test/java/io/seata/tm/api/transaction/TransactionHookManagerTest.java b/tm/src/test/java/io/seata/tm/api/transaction/TransactionHookManagerTest.java
index d37ba09be2c146bf9437dcc70944c26d00e8ef40..55942e4cb49dee1cb11632c552d4696a7c0fe4d1 100644
--- a/tm/src/test/java/io/seata/tm/api/transaction/TransactionHookManagerTest.java
+++ b/tm/src/test/java/io/seata/tm/api/transaction/TransactionHookManagerTest.java
@@ -15,8 +15,8 @@
  */
 package io.seata.tm.api.transaction;
 
-import org.junit.After;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
 
 import java.util.List;
 
@@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
  */
 public class TransactionHookManagerTest {
 
-    @After
+    @AfterEach
     public void clear() {
         TransactionHookManager.clear();
     }
diff --git a/tm/src/test/java/io/seata/tm/api/transaction/TransactionInfoTest.java b/tm/src/test/java/io/seata/tm/api/transaction/TransactionInfoTest.java
index 40b413982de71eeca008216196df901ad8ba80e6..81372d2eb11b6c5d36e282d71b36d91e282539fb 100644
--- a/tm/src/test/java/io/seata/tm/api/transaction/TransactionInfoTest.java
+++ b/tm/src/test/java/io/seata/tm/api/transaction/TransactionInfoTest.java
@@ -19,7 +19,7 @@ import com.alibaba.fastjson.JSON;
 import io.seata.tm.api.transaction.NoRollbackRule;
 import io.seata.tm.api.transaction.RollbackRule;
 import io.seata.tm.api.transaction.TransactionInfo;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
 import java.util.LinkedHashSet;