tcc-transaction

来源:9-18 流程演示以及jar包调整

Moss1105

2020-02-23

老师,我在使用tcc-transaction时,只能调用到服务消费者端的confirm或cancel方法,并不能调用到服务提供者端的confirm或cancel方法。下面是我的代码,请您帮忙看下问题出在哪里?

第一种情况

服务接口com.example.api.transaction.TransactionServiceAPI

public interface TransactionServiceAPI {

    @Compensable
    void sendMessage(String message);

}

服务提供者com.example.provider.service.impl.transaction.TransactionServiceImpl

@Component
@Service(interfaceClass = TransactionServiceAPI.class)
public class TransactionServiceImpl implements TransactionServiceAPI {
    @Override
    @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", transactionContextEditor = DubboTransactionContextEditor.class)
    public void sendMessage(String message) {
        System.out.println("provider try");
        if (message.equals("123")) {
            throw new NullPointerException();
        }
    }


    public void confirmSendMessage(String message) {
        System.out.println("provider confirm");
    }

    public void cancelSendMessage(String message) {
        System.out.println("provider cancel");
    }

}

服务消费者com.example.consumer.transaction.TransactionConsumer

@Component
public class TransactionConsumer {

    @Autowired
    TransactionServiceAPI transactionServiceAPI;

    @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", transactionContextEditor = DubboTransactionContextEditor.class)
    public void sendMessage(String message) {
        System.out.println("consumer try");
        transactionServiceAPI.sendMessage(message);
    }


    public void confirmSendMessage(String message) {
        System.out.println("consumer confirm");
    }

    public void cancelSendMessage(String message) {
        System.out.println("consumer cancel");
    }
}

服务消费者端的tcc-transaction-dubbo.xml

 <dubbo:registry protocol="zookeeper" address="182.61.22.173:2181"/>
    <dubbo:application name="transaction-consumer" />
    <dubbo:reference id="transactionServiceAPI" timeout="50000" interface="com.example.api.transaction.TransactionServiceAPI" />

服务消费者端启动类com.example.consumer.ConsumerApplication

@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(ConsumerApplication.class, args);
        TransactionConsumer transactionConsumer = (TransactionConsumer)run.getBean("transactionConsumer");
        transactionConsumer.sendMessage("123");
    }

}

运行结果:
服务消费者端输出如下:

consumer try
consumer cancel
Exception in thread "main" java.lang.NullPointerException

服务提供者端输出如下:

provider try

我的问题:照理说,服务提供者端不是应该输出以下内容吗?

provider try
provider cancel

但是,实际情况并没有输出provider cancel,也就是服务提供者端没有调用到cancel方法。

第二种情况

服务接口TransactionServiceAPI

public interface TransactionServiceAPI {

    /**
     * 背景:传入购票数量、传入购买座位、影厅编号
     * 业务:
     * 1. 判断传入的座位是否存在
     * 2. 查询过往订单,判断座位是否已售
     * 3. 新增订单
     * 逻辑:
     * 1. 新增一条订单
     * 2. 判断作为是否存在 & 是否已售
     * 3. 任意一条为假,则修改订单为无效状态
     */

    //判断是否为真座位
    @Compensable
    boolean isTrueSeats(String seats);

    //是否已售
    @Compensable
    boolean isNotSold(String seats);

    //保存订单
    @Compensable
    String saveOrder(String fieldId, String seats, String seatsNum);

}

服务提供者TransactionServiceImpl

@Component
@Service(interfaceClass = TransactionServiceAPI.class)
public class TransactionServiceImpl implements TransactionServiceAPI {
    @Override
    @Compensable(confirmMethod = "confirmSendMessage", cancelMethod = "cancelSendMessage", transactionContextEditor = DubboTransactionContextEditor.class)
    public void sendMessage(String message) {
        System.out.println("provider try");
        if (message.equals("123")) {
            throw new NullPointerException();
        }
    }

    @Override
    @Compensable(confirmMethod = "confirmIsTrueSeats", cancelMethod = "cancelIsTrueSeats", transactionContextEditor = DubboTransactionContextEditor.class)
    public boolean isTrueSeats(String seats) {
        System.out.println("provider isTrueSeats");
        if(seats.equals("1,2,3")){
            throw new IllegalArgumentException();
        }
        return true;
    }

    @Override
    @Compensable(confirmMethod = "confirmIsNotSold", cancelMethod = "cancelIsNotSold", transactionContextEditor = DubboTransactionContextEditor.class)
    public boolean isNotSold(String seats) {
        System.out.println("provider isNotSold");
        if(seats.equals("4,5")){
            throw new IllegalArgumentException();
        }
        return true;
    }

    /**
     * 千万注意幂等性的问题
     * @param fieldId
     * @param seats
     * @param seatsNum
     * @return
     */
    @Override
    @Compensable(confirmMethod = "confirmSaveOrder", cancelMethod = "cancelSaveOrder", transactionContextEditor = DubboTransactionContextEditor.class)
    public String saveOrder(String fieldId, String seats, String seatsNum) {
        System.out.println("provider saveOrder");
        return "";
    }

    public String confirmSaveOrder(String fieldId, String seats, String seatsNum) {
        System.out.println("provider confirmSaveOrder");
        return "";
    }

    public String cancelSaveOrder(String fieldId, String seats, String seatsNum) {
        System.out.println("provider cancelSaveOrder");
        return "";
    }


    public boolean confirmIsTrueSeats(String seats) {
        System.out.println("provider confirmIsTrueSeats");
        return true;
    }

    public boolean cancelIsTrueSeats(String seats) {
        System.out.println("provider cancelIsTrueSeats");
        return true;
    }

    public boolean confirmIsNotSold(String seats) {
        System.out.println("provider confirmIsNotSold");
        return true;
    }

    public boolean cancelIsNotSold(String seats) {
        System.out.println("provider cancelIsNotSold");
        return true;
    }

}

服务消费者TransactionServiceAPI

@Component
public class TransactionConsumer {

    @Autowired
    TransactionServiceAPI transactionServiceAPI;

    @Compensable(confirmMethod = "confirmOrder", cancelMethod = "cancelOrder", transactionContextEditor = DubboTransactionContextEditor.class)
    public void order(String message) {
        transactionServiceAPI.saveOrder("001", message, "5");
        transactionServiceAPI.isTrueSeats(message);
        transactionServiceAPI.isNotSold(message);
    }

    public void confirmOrder(String message) {
        System.out.println("consumer confirmOrder");
    }

    public void cancelOrder(String message) {
        System.out.println("consumer cancelOrder");
    }
}

服务消费者端启动类ConsumerApplication

@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(ConsumerApplication.class, args);
        TransactionConsumer transactionConsumer = (TransactionConsumer) run.getBean("transactionConsumer");
        transactionConsumer.order("4,5");
    }

}

运行结果:
服务消费者端输出:

consumer cancelOrder
Exception in thread "main" java.lang.IllegalArgumentException

服务提供者端输出:

provider saveOrder
provider isTrueSeats
provider isNotSold
provider cancelIsTrueSeats
provider cancelIsNotSold

我真的懵了,不知道问题出在哪?

写回答

1回答

Allen

2020-02-23

错误内容多截一些图, 这个错误提示不太明确

0
2
Moss1105
我先把tcc-transaction给的dubbo示例跑一下,看一下运行结果,想想问题出在哪
2020-02-23
共2条回复

Dubbo主流版本打造仿猫眼项目 理解微服务核心思想

实战Dubbo项目+面试技巧,老司机带你畅游微服务

1410 学习 · 582 问题

查看课程