001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.support.seata.filter;
017
018import com.jfinal.log.Log;
019import io.jboot.support.seata.JbootSeataManager;
020import io.seata.core.context.RootContext;
021import org.apache.dubbo.common.extension.Activate;
022import org.apache.dubbo.rpc.*;
023
024/**
025 * The type Transaction propagation filter.
026 */
027@Activate(group = {"provider", "consumer"}, order = 100)
028public class TransactionPropagationFilter implements Filter {
029
030    private static final Log LOGGER = Log.getLog(TransactionPropagationFilter.class);
031
032    @Override
033    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
034        if (!JbootSeataManager.me().isEnable()){
035            return invoker.invoke(invocation);
036        }
037        String xid = RootContext.getXID();
038        String rpcXid = RpcContext.getContext().getAttachment(RootContext.KEY_XID);
039        if (LOGGER.isDebugEnabled()) {
040            LOGGER.debug("xid in RootContext[" + xid + "] xid in RpcContext[" + rpcXid + "]");
041        }
042        boolean bind = false;
043        if (xid != null) {
044            RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid);
045        } else {
046            if (rpcXid != null) {
047                RootContext.bind(rpcXid);
048                bind = true;
049                if (LOGGER.isDebugEnabled()) {
050                    LOGGER.debug("bind[" + rpcXid + "] to RootContext");
051                }
052            }
053        }
054        try {
055            return invoker.invoke(invocation);
056        } finally {
057            if (bind) {
058                String unbindXid = RootContext.unbind();
059                if (LOGGER.isDebugEnabled()) {
060                    LOGGER.debug("unbind[" + unbindXid + "] from RootContext");
061                }
062                if (!rpcXid.equalsIgnoreCase(unbindXid)) {
063                    LOGGER.warn("xid in change during RPC from " + rpcXid + " to " + unbindXid);
064                    if (unbindXid != null) {
065                        RootContext.bind(unbindXid);
066                        LOGGER.warn("bind [" + unbindXid + "] back to RootContext");
067                    }
068                }
069            }
070        }
071    }
072}