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;
017
018import com.jfinal.log.Log;
019import io.seata.common.util.StringUtils;
020import io.seata.config.ConfigurationFactory;
021import io.seata.core.rpc.ShutdownHook;
022import io.seata.core.rpc.netty.RmNettyRemotingClient;
023import io.seata.core.rpc.netty.TmNettyRemotingClient;
024import io.seata.rm.RMClient;
025import io.seata.tm.TMClient;
026import io.seata.tm.api.DefaultFailureHandlerImpl;
027import io.seata.tm.api.FailureHandler;
028
029
030public class SeataGlobalTransactionManager {
031
032    @SuppressWarnings("unused")
033        private static final long serialVersionUID = 1L;
034    private static final Log LOGGER = Log.getLog(SeataGlobalTransactionManager.class);
035
036
037    @SuppressWarnings("unused")
038        private final FailureHandler failureHandlerHook;
039    private static final FailureHandler DEFAULT_FAIL_HANDLER = new DefaultFailureHandlerImpl();
040    private final boolean disableGlobalTransaction = ConfigurationFactory.getInstance()
041            .getBoolean("service.disableGlobalTransaction", false);
042
043
044    private static final int AT_MODE = 1;
045    private static final int MT_MODE = 2;
046
047
048    private static final int DEFAULT_MODE = AT_MODE + MT_MODE;
049    @SuppressWarnings("unused")
050        private static final int ORDER_NUM = 1024;
051
052
053    private final String applicationId;
054    private final String txServiceGroup;
055    @SuppressWarnings("unused")
056        private final int mode;
057
058
059    /**
060     * Instantiates a new Global transaction manager.
061     *
062     * @param txServiceGroup the tx service group
063     */
064    public SeataGlobalTransactionManager(String txServiceGroup) {
065        this(txServiceGroup, txServiceGroup, DEFAULT_MODE);
066    }
067
068    /**
069     * Instantiates a new Global transaction manager.
070     *
071     * @param txServiceGroup the tx service group
072     * @param mode           the mode
073     */
074    public SeataGlobalTransactionManager(String txServiceGroup, int mode) {
075        this(txServiceGroup, txServiceGroup, mode);
076    }
077
078    /**
079     * Instantiates a new Global transaction manager.
080     *
081     * @param applicationId  the application id
082     * @param txServiceGroup the default server group
083     */
084    public SeataGlobalTransactionManager(String applicationId, String txServiceGroup) {
085        this(applicationId, txServiceGroup, DEFAULT_MODE);
086    }
087
088    /**
089     * Instantiates a new Global transaction manager.
090     *
091     * @param applicationId  the application id
092     * @param txServiceGroup the tx service group
093     * @param mode           the mode
094     */
095    public SeataGlobalTransactionManager(String applicationId, String txServiceGroup, int mode) {
096        this(applicationId, txServiceGroup, mode, DEFAULT_FAIL_HANDLER);
097    }
098
099    public SeataGlobalTransactionManager(String applicationId, String txServiceGroup,
100                                          FailureHandler failureHandlerHook) {
101        this(applicationId, txServiceGroup, DEFAULT_MODE, failureHandlerHook);
102    }
103
104    public SeataGlobalTransactionManager(String applicationId, String txServiceGroup, int mode,
105                                          FailureHandler failureHandler) {
106        this.applicationId = applicationId;
107        this.txServiceGroup = txServiceGroup;
108        this.mode = mode;
109        this.failureHandlerHook = failureHandler;
110    }
111
112    private void initClient() {
113        if (LOGGER.isInfoEnabled()) {
114            LOGGER.info("Initializing Global Transaction Clients ... ");
115        }
116        if (StringUtils.isNullOrEmpty(applicationId) || StringUtils.isNullOrEmpty(txServiceGroup)) {
117            throw new IllegalArgumentException(
118                    "applicationId: " + applicationId + ", txServiceGroup: " + txServiceGroup);
119        }
120        //init TM
121        TMClient.init(applicationId, txServiceGroup);
122        if (LOGGER.isInfoEnabled()) {
123            LOGGER.info(
124                    "Transaction Manager Client is initialized. applicationId[" + applicationId + "] txServiceGroup["
125                            + txServiceGroup + "]");
126        }
127        //init RM
128        RMClient.init(applicationId, txServiceGroup);
129        if (LOGGER.isInfoEnabled()) {
130            LOGGER.info("Resource Manager is initialized. applicationId[" + applicationId + "] txServiceGroup[" + txServiceGroup + "]");
131        }
132
133        if (LOGGER.isInfoEnabled()) {
134            LOGGER.info("Global Transaction Clients are initialized. ");
135        }
136
137        registerSpringShutdownHook();
138    }
139
140
141    private void registerSpringShutdownHook() {
142        ShutdownHook.removeRuntimeShutdownHook();
143        ShutdownHook.getInstance().addDisposable(TmNettyRemotingClient.getInstance(applicationId, txServiceGroup));
144        ShutdownHook.getInstance().addDisposable(RmNettyRemotingClient.getInstance(applicationId, txServiceGroup));
145    }
146
147    public void destroy() {
148        ShutdownHook.getInstance().destroyAll();
149    }
150
151    public void init() {
152        if (disableGlobalTransaction) {
153            if (LOGGER.isInfoEnabled()) {
154                LOGGER.info("Global transaction is disabled.");
155            }
156            return;
157        }
158        initClient();
159    }
160}