Backend Development 19 min read

How to Integrate Dubbo with Seata for Distributed Transactions in Spring Boot

This tutorial walks through integrating Dubbo with Seata in a Spring Boot microservice architecture, showing how to create service interfaces, configure Maven dependencies, set up Nacos discovery, implement distributed transaction logic, test normal and rollback scenarios, and externalize Seata server addresses for scalable deployments.

macrozheng
macrozheng
macrozheng
How to Integrate Dubbo with Seata for Distributed Transactions in Spring Boot

Background

In a previous article we introduced Seata’s architecture, deployment, and basic usage. Within the Spring Cloud ecosystem there are two ways to perform remote service calls: HTTP tools such as OpenFeign or HttpClient, and Dubbo which uses TCP for higher efficiency.

Because many domestic projects use Dubbo for remote calls, we will use Dubbo as an example to show how to integrate it with Seata for distributed transaction handling.

Solution Practice

We modify an existing project and illustrate the interaction flow with a diagram.

2.1 Create Service Interface

Create a Maven module

seata-dubbo-api

and define the service interface:

<code>public interface StockApi {
    /**
     * 库存扣减
     */
    boolean deduct(String productCode, int count);
}</code>

After the interface is ready, we will create the stock service and order service.

2.2 Create Stock Service

Create a Spring Boot project

seata-dubbo-stock

and add the following dependencies in

pom.xml

:

<code>&lt;properties&gt;
    &lt;maven.compiler.source&gt;8&lt;/maven.compiler.source&gt;
    &lt;maven.compiler.target&gt;8&lt;/maven.compiler.target&gt;
    &lt;spring-boot.version&gt;2.2.5.RELEASE&lt;/spring-boot.version&gt;
    &lt;spring-cloud.version&gt;Hoxton.SR3&lt;/spring-cloud.version&gt;
    &lt;spring-cloud-alibaba.version&gt;2.2.1.RELEASE&lt;/spring-cloud-alibaba.version&gt;
&lt;/properties&gt;

&lt;dependencies&gt;
    &lt;!-- SpringBoot web --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;!-- MySQL driver --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;mysql&lt;/groupId&gt;
        &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;!-- MyBatis --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt;
        &lt;artifactId&gt;mybatis-spring-boot-starter&lt;/artifactId&gt;
        &lt;version&gt;2.0.0&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!-- Nacos discovery --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-starter-alibaba-nacos-discovery&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;!-- Dubbo --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-starter-dubbo&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;!-- Seata distributed transaction component --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
        &lt;artifactId&gt;spring-cloud-starter-alibaba-seata&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;!-- API module dependency --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.example&lt;/groupId&gt;
        &lt;artifactId&gt;seata-dubbo-api&lt;/artifactId&gt;
        &lt;version&gt;3.0-SNAPSHOT&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;

&lt;dependencyManagement&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-boot.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-cloud.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.alibaba.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-alibaba-dependencies&lt;/artifactId&gt;
            &lt;version&gt;${spring-cloud-alibaba.version}&lt;/version&gt;
            &lt;type&gt;pom&lt;/type&gt;
            &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/dependencyManagement&gt;</code>

Add

application.properties

with the following configuration:

<code>spring.application.name=seata-dubbo-stock
server.port=9002

# Data source
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata-stock
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# MyBatis
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

# Nacos discovery
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

# Dubbo settings
dubbo.scan.base-packages=com.example.cloud.nacos.dubbo.seata
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.registry.address=nacos://${spring.cloud.nacos.discovery.server-addr}

# Seata settings
seata.application-id=seata-dubbo-stock
seata.tx-service-group=my_test_tx_group
seata.service.vgroup-mapping.my_test_tx_group=default
seata.service.grouplist.default=127.0.0.1:8091</code>

Implement the Dubbo service:

<code>@com.alibaba.dubbo.config.annotation.Service
public class StockApiImpl implements StockApi {
    @Autowired
    private StockService stockService;

    @Override
    public boolean deduct(String productCode, int count) {
        try {
            stockService.deduct(productCode, count);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}</code>

Start the service with

@EnableDiscoveryClient

and a main class.

<code>@EnableDiscoveryClient
@MapperScan("com.example.cloud.nacos.dubbo.seata")
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}</code>

2.3 Create Order Service

Create another Spring Boot project

seata-dubbo-order

with the same dependencies and configuration as the stock service. Replace the HTTP‑based remote call with a Dubbo reference:

<code>@Component
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @com.alibaba.dubbo.config.annotation.Reference
    private StockApi stockApi;

    @GlobalTransactional
    public void create(String userId, String productCode, int orderCount) throws Exception {
        // Remote stock deduction via Dubbo
        stockApi.deduct(productCode, orderCount);
        Order order = new Order();
        order.setUserId(userId);
        order.setProductCode(productCode);
        order.setCount(orderCount);
        order.setMoney(orderCount * 100);
        orderMapper.insert(order);
    }
}</code>

Corresponding

application.properties

mirrors the stock service configuration, with its own service name and port.

2.4 Service Testing

Two test cases are performed:

Distributed transaction normal commit – calling

http://127.0.0.1:9001/order/create?userId=张三&productCode=wahaha&orderCount=1

should deduct stock and insert an order.

Distributed transaction exception rollback – modify

OrderService.create()

to throw an exception after the order is created, then verify that both stock and order tables remain unchanged.

Database snapshots and Seata TC server logs confirm the expected behavior in both scenarios.

Seata Service Address Configuration

When the number of Seata TC servers grows, hard‑coding their addresses becomes unwieldy. By registering the Seata server in a service registry (e.g., Nacos), clients can discover the address dynamically.

3.1 Seata Server Configuration

Copy the

store.registry

section from

conf/application.example.yml

to

conf/application.yml

and restart the Seata TC server. The server will appear in the Nacos console.

3.2 Seata Client Configuration

In the client’s

application.properties

add:

<code># Seata identifiers
seata.application-id=seata-dubbo-stock
seata.tx-service-group=my_test_tx_group
seata.service.vgroup-mapping.my_test_tx_group=default

# Registry type
seata.registry.type=nacos
seata.registry.nacos.application=seata-server
seata.registry.nacos.server-addr=127.0.0.1:8848
seata.registry.nacos.group=SEATA_GROUP</code>

Restart the services; the client now obtains the TC server address from Nacos.

3.3 Error Troubleshooting

If an error such as version incompatibility appears, verify that the Seata client version matches the server version. For example, upgrading

spring-cloud-alibaba

from

2.2.1.RELEASE

to

2.2.3.RELEASE

brings the embedded Seata client to

1.3.0

, which is compatible with a server version

1.5.2

.

Conclusion

This article demonstrated how to integrate Dubbo with Seata to achieve distributed transaction management in a Spring Boot microservice environment, covering service creation, configuration, testing, dynamic address discovery, and common pitfalls.

MicroservicesDubboSpring Bootdistributed transactionsseata
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.