All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.transaction.client.spi.LocalTransactionProvider Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2016 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * 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 org.wildfly.transaction.client.spi;

import jakarta.transaction.HeuristicMixedException;
import jakarta.transaction.HeuristicRollbackException;
import jakarta.transaction.InvalidTransactionException;
import jakarta.transaction.NotSupportedException;
import jakarta.transaction.RollbackException;
import jakarta.transaction.Status;
import jakarta.transaction.Synchronization;
import jakarta.transaction.SystemException;
import jakarta.transaction.Transaction;
import jakarta.transaction.TransactionManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;

import org.wildfly.common.Assert;
import org.wildfly.common.annotation.NotNull;
import org.wildfly.transaction.client.ImportResult;
import org.wildfly.transaction.client.LocalTransaction;
import org.wildfly.transaction.client.SimpleXid;
import org.wildfly.transaction.client.XAImporter;
import org.wildfly.transaction.client.XAResourceRegistry;
import org.wildfly.transaction.client._private.Log;

/**
 * A local transaction provider.  Such a provider must implement all methods on this interface in order for
 * local transactions to be supported.
 *
 * @author David M. Lloyd
 */
public interface LocalTransactionProvider extends TransactionProvider {
    /**
     * Get the transaction manager.
     *
     * @return the transaction manager (must not be {@code null})
     */
    @NotNull
    TransactionManager getTransactionManager();

    /**
     * Get the XA importer.
     *
     * @return the XA importer (must not be {@code null})
     */
    @NotNull
    XAImporter getXAImporter();

    /**
     * Create and start a new local transaction, which is not associated with any particular thread.
     *
     * @param timeout the timeout to use for the new transaction
     * @return the new transaction (must not be {@code null})
     * @throws SystemException if the creation of the transaction failed for some reason
     * @throws SecurityException if the caller is not authorized to create a transaction
     */
    @NotNull
    Transaction createNewTransaction(final int timeout) throws SystemException, SecurityException;

    /**
     * Determine whether the given transaction was imported or originated locally.
     *
     * @param transaction the transaction to test (not {@code null})
     * @return {@code true} if the transaction was imported, or {@code false} if it was created locally
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    boolean isImported(@NotNull Transaction transaction) throws IllegalArgumentException;

    /**
     * Register an interposed synchronization on the given transaction.
     *
     * @param transaction the transaction (not {@code null})
     * @param sync the synchronization (not {@code null})
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    void registerInterposedSynchronization(@NotNull Transaction transaction, @NotNull Synchronization sync) throws IllegalArgumentException;

    /**
     * Get a resource associated with the given transaction.
     *
     * @param transaction the transaction (not {@code null})
     * @param key the key to look up (not {@code null})
     * @return the resource, or {@code null} if none is set
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    Object getResource(@NotNull Transaction transaction, @NotNull Object key);

    /**
     * Put a resource on to the given transaction.
     *
     * @param transaction the transaction (not {@code null})
     * @param key the key to store under (not {@code null})
     * @param value the value to store
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    void putResource(@NotNull Transaction transaction, @NotNull Object key, Object value) throws IllegalArgumentException;

    /**
     * Put a resource on to the given transaction if the resource does not already exist.  Providers which do not
     * support this operation must emulate it.
     *
     * @param transaction the transaction (must not be {@code null})
     * @param key the key to store under (not {@code null})
     * @param value the value to store
     * @return the existing value, or {@code null} if none is set
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    Object putResourceIfAbsent(@NotNull Transaction transaction, @NotNull Object key, Object value) throws IllegalArgumentException;

    /**
     * Determine if the given transaction is rollback-only.
     *
     * @param transaction the transaction (not {@code null})
     * @return {@code true} if the transaction is rollback-only, {@code false} otherwise
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    boolean getRollbackOnly(@NotNull Transaction transaction) throws IllegalArgumentException;

    /**
     * Get a key which has the same equals and hashCode behavior as the given transaction.
     *
     * @param transaction the transaction (not {@code null})
     * @return the key object (must not be {@code null})
     * @throws IllegalArgumentException if the transaction does not belong to this provider
     */
    @NotNull Object getKey(@NotNull Transaction transaction) throws IllegalArgumentException;

    /**
     * Locally commit the given provider transaction.  A given provider transaction will only be committed by this
     * method or {@link SubordinateTransactionControl#commit(boolean)}.
     *
     * @param transaction the transaction (not {@code null})
     * @throws RollbackException if the local commit operation throws this exception
     * @throws HeuristicMixedException if the local commit operation throws this exception
     * @throws HeuristicRollbackException if the local commit operation throws this exception
     * @throws SecurityException if the local commit operation throws this exception
     * @throws IllegalStateException if the local commit operation throws this exception
     * @throws SystemException if the local commit operation throws this exception
     */
    void commitLocal(@NotNull Transaction transaction) throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException;

    /**
     * Locally roll back the given provider transaction.  A given provider transaction will only be rolled back by this
     * method or {@link SubordinateTransactionControl#rollback()}.
     *
     * @param transaction the transaction (not {@code null})
     * @throws IllegalStateException if the local commit operation throws this exception
     * @throws SystemException if the local commit operation throws this exception
     */
    void rollbackLocal(@NotNull Transaction transaction) throws IllegalStateException, SystemException;

    /**
     * Drop a local transaction from memory.  The transaction is locally-initiated and contains no remote subordinate
     * enlistments, guaranteeing that the transaction can never reappear on this node.
     *
     * @param transaction the transaction to drop (not {@code null})
     */
    void dropLocal(@NotNull Transaction transaction);

    /**
     * The transaction is expected to work with outflowed resources - it contains a remote subordinate enlistment.
     * We can't use the {@link #dropLocal(Transaction)} directly as the the transaction may reapear
     * on this node during recovery.
     *
     * But this method gives a chance to the provider to reassign the removal timeout or some other work
     * that needs to be done in case the in-flight transaction finished.
     *
     * @param transaction the transaction with ouflowed resources to announce of being finished (not {@code null})
     */
    void dropRemote(@NotNull Transaction transaction);

    /**
     * Get the configured timeout of the given transaction (not the remaining time).
     *
     * @param transaction the transaction (not {@code null})
     * @return the number of seconds remaining
     */
    int getTimeout(@NotNull Transaction transaction);

    /**
     * Get the transaction ID of the given transaction.
     *
     * @param transaction the transaction (not {@code null})
     * @return the transaction ID (must not be {@code null})
     */
    @NotNull Xid getXid(@NotNull Transaction transaction);

    /**
     * Get the unique node name of this provider.
     *
     * @return the node name (must not be {@code null})
     */
    @NotNull
    String getNodeName();

    /**
     * Attempt to derive a node name from an XID.  If the XID is not in a recognized format, {@code null} is returned.
     *
     * @param xid the XID (not {@code null})
     * @return the originating node name
     */
    default String getNameFromXid(@NotNull Xid xid) {
        return null;
    }

    /**
     * Attempt to acquire a provider interface instance from the given provider transaction.
     *
     * @param transaction the provider transaction (not {@code null})
     * @param providerInterfaceType the provider interface type class (not {@code null})
     * @param  the provider interface type
     * @return the provider interface instance, or {@code null} if none matches
     */
    default  T getProviderInterface(Transaction transaction, Class providerInterfaceType) {
        return null;
    }

    /**
     * Return the XAResource registry associated with {@code transaction}. If there is no such
     * registry yet, one is created.
     *
     * @param transaction the transaction
     * @return the registry associated with {@code transaction}. Can return {@code null} if this
     * provider requires no XAResource registry
     */
    default XAResourceRegistry getXAResourceRegistry(LocalTransaction transaction) throws SystemException {
        return null;
    }

    /**
     * An empty provider which does not support new transactions.
     */
    LocalTransactionProvider EMPTY = new LocalTransactionProvider() {

        private final TransactionManager transactionManager = new TransactionManager() {
            public void begin() throws NotSupportedException, SystemException {
                throw Assert.unsupported();
            }

            public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
                throw Log.log.noTransaction();
            }

            public void rollback() throws IllegalStateException, SecurityException, SystemException {
                throw Log.log.noTransaction();
            }

            public void setRollbackOnly() throws IllegalStateException, SystemException {
                throw Log.log.noTransaction();
            }

            public int getStatus() throws SystemException {
                return Status.STATUS_NO_TRANSACTION;
            }

            public Transaction getTransaction() throws SystemException {
                return null;
            }

            public void setTransactionTimeout(final int seconds) throws SystemException {
                // ignored
            }

            public Transaction suspend() throws SystemException {
                throw Log.log.noTransaction();
            }

            public void resume(final Transaction tobj) throws InvalidTransactionException, IllegalStateException, SystemException {
                throw Log.log.transactionNotAssociatedWithThisProvider();
            }
        };
        private final XAImporter xaImporter = new XAImporter() {
            public ImportResult findOrImportTransaction(final Xid xid, final int timeout, final boolean doNotImport) throws XAException {
                if (doNotImport) return null; else throw Assert.unsupported();
            }

            public Transaction findExistingTransaction(final Xid xid) throws XAException {
                return null;
            }

            public void commit(final Xid xid, final boolean onePhase) throws XAException {
                throw Log.log.noTransactionXa(XAException.XAER_NOTA);
            }

            public void forget(final Xid xid) throws XAException {
                throw Log.log.noTransactionXa(XAException.XAER_NOTA);
            }

            @NotNull
            public Xid[] recover(final int flag, final String parentName) throws XAException {
                return SimpleXid.NO_XIDS;
            }
        };

        @NotNull
        public TransactionManager getTransactionManager() {
            return transactionManager;
        }

        @NotNull
        public XAImporter getXAImporter() {
            return xaImporter;
        }

        @NotNull
        public Transaction createNewTransaction(final int timeout) throws SystemException, SecurityException {
            throw Assert.unsupported();
        }

        public boolean isImported(@NotNull final Transaction transaction) throws IllegalArgumentException {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        public void registerInterposedSynchronization(@NotNull final Transaction transaction, @NotNull final Synchronization sync) throws IllegalArgumentException {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        public Object getResource(@NotNull final Transaction transaction, @NotNull final Object key) {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        public void putResource(@NotNull final Transaction transaction, @NotNull final Object key, final Object value) throws IllegalArgumentException {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        public Object putResourceIfAbsent(@NotNull final Transaction transaction, @NotNull final Object key, final Object value) throws IllegalArgumentException {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        public boolean getRollbackOnly(@NotNull final Transaction transaction) throws IllegalArgumentException {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        @NotNull
        public Object getKey(@NotNull final Transaction transaction) throws IllegalArgumentException {
            throw new IllegalArgumentException(Log.log.transactionNotAssociatedWithThisProvider().getMessage());
        }

        public void commitLocal(@NotNull final Transaction transaction) throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
            throw Log.log.noTransaction();
        }

        public void rollbackLocal(@NotNull final Transaction transaction) throws IllegalStateException, SystemException {
            throw Log.log.noTransaction();
        }

        public void dropLocal(@NotNull final Transaction transaction) {
            // no operation
        }

        public void dropRemote(@NotNull final Transaction transaction) {
            // no operation
        }

        @NotNull
        public Xid getXid(@NotNull final Transaction transaction) {
            throw Log.log.noTransaction();
        }

        public int getTimeout(@NotNull final Transaction transaction) {
            throw Log.log.noTransaction();
        }

        @NotNull
        public String getNodeName() {
            return "<>";
        }
    };
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy