Skip to content

Commit beea83b

Browse files
mp911dejhoeller
authored andcommitted
Add reactive transaction support SPI
This commit adds SPI interfaces to support reactive transactions through spring-tx with optional dependencies to Project Reactor and supportive implementations for TransactionalOperator and AbstractReactiveTransactionManager.
1 parent cee7d09 commit beea83b

20 files changed

+3891
-0
lines changed

spring-tx/spring-tx.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
description = "Spring Transaction"
22

3+
dependencyManagement {
4+
imports {
5+
mavenBom "io.projectreactor:reactor-bom:${reactorVersion}"
6+
}
7+
}
8+
39
dependencies {
410
compile(project(":spring-beans"))
511
compile(project(":spring-core"))
@@ -10,8 +16,10 @@ dependencies {
1016
optional("javax.resource:javax.resource-api:1.7.1")
1117
optional("javax.transaction:javax.transaction-api:1.3")
1218
optional("com.ibm.websphere:uow:6.0.2.17")
19+
optional("io.projectreactor:reactor-core")
1320
optional("io.vavr:vavr:0.10.0")
1421
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
1522
testCompile("org.codehaus.groovy:groovy:${groovyVersion}")
1623
testCompile("org.eclipse.persistence:javax.persistence:2.2.0")
24+
testCompile("io.projectreactor:reactor-test")
1725
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.transaction;
18+
19+
import reactor.core.publisher.Mono;
20+
21+
import org.springframework.lang.Nullable;
22+
23+
/**
24+
* This is the central interface in Spring's reactive transaction infrastructure.
25+
* Applications can use this directly, but it is not primarily meant as API:
26+
* Typically, applications will work with either transactional operators or
27+
* declarative transaction demarcation through AOP.
28+
*
29+
* @author Mark Paluch
30+
* @since 5.2
31+
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
32+
*/
33+
public interface ReactiveTransactionManager {
34+
35+
/**
36+
* Emit a currently active transaction or create a new one, according to
37+
* the specified propagation behavior.
38+
* <p>Note that parameters like isolation level or timeout will only be applied
39+
* to new transactions, and thus be ignored when participating in active ones.
40+
* <p>Furthermore, not all transaction definition settings will be supported
41+
* by every transaction manager: A proper transaction manager implementation
42+
* should throw an exception when unsupported settings are encountered.
43+
* <p>An exception to the above rule is the read-only flag, which should be
44+
* ignored if no explicit read-only mode is supported. Essentially, the
45+
* read-only flag is just a hint for potential optimization.
46+
* @param definition the TransactionDefinition instance (can be empty for defaults),
47+
* describing propagation behavior, isolation level, timeout etc.
48+
* @return transaction status object representing the new or current transaction
49+
* @throws TransactionException in case of lookup, creation, or system errors
50+
* @throws IllegalTransactionStateException if the given transaction definition
51+
* cannot be executed (for example, if a currently active transaction is in
52+
* conflict with the specified propagation behavior)
53+
* @see TransactionDefinition#getPropagationBehavior
54+
* @see TransactionDefinition#getIsolationLevel
55+
* @see TransactionDefinition#getTimeout
56+
* @see TransactionDefinition#isReadOnly
57+
*/
58+
Mono<ReactiveTransactionStatus> getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
59+
60+
/**
61+
* Commit the given transaction, with regard to its status. If the transaction
62+
* has been marked rollback-only programmatically, perform a rollback.
63+
* <p>If the transaction wasn't a new one, omit the commit for proper
64+
* participation in the surrounding transaction. If a previous transaction
65+
* has been suspended to be able to create a new one, resume the previous
66+
* transaction after committing the new one.
67+
* <p>Note that when the commit call completes, no matter if normally or
68+
* throwing an exception, the transaction must be fully completed and
69+
* cleaned up. No rollback call should be expected in such a case.
70+
* <p>If this method throws an exception other than a TransactionException,
71+
* then some before-commit error caused the commit attempt to fail. For
72+
* example, an O/R Mapping tool might have tried to flush changes to the
73+
* database right before commit, with the resulting DataAccessException
74+
* causing the transaction to fail. The original exception will be
75+
* propagated to the caller of this commit method in such a case.
76+
* @param status object returned by the {@code getTransaction} method
77+
* @throws UnexpectedRollbackException in case of an unexpected rollback
78+
* that the transaction coordinator initiated
79+
* @throws HeuristicCompletionException in case of a transaction failure
80+
* caused by a heuristic decision on the side of the transaction coordinator
81+
* @throws TransactionSystemException in case of commit or system errors
82+
* (typically caused by fundamental resource failures)
83+
* @throws IllegalTransactionStateException if the given transaction
84+
* is already completed (that is, committed or rolled back)
85+
* @see ReactiveTransactionStatus#setRollbackOnly
86+
*/
87+
Mono<Void> commit(ReactiveTransactionStatus status) throws TransactionException;
88+
89+
/**
90+
* Perform a rollback of the given transaction.
91+
* <p>If the transaction wasn't a new one, just set it rollback-only for proper
92+
* participation in the surrounding transaction. If a previous transaction
93+
* has been suspended to be able to create a new one, resume the previous
94+
* transaction after rolling back the new one.
95+
* <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
96+
* The transaction will already have been completed and cleaned up when commit
97+
* returns, even in case of a commit exception. Consequently, a rollback call
98+
* after commit failure will lead to an IllegalTransactionStateException.
99+
* @param status object returned by the {@code getTransaction} method
100+
* @throws TransactionSystemException in case of rollback or system errors
101+
* (typically caused by fundamental resource failures)
102+
* @throws IllegalTransactionStateException if the given transaction
103+
* is already completed (that is, committed or rolled back)
104+
*/
105+
Mono<Void> rollback(ReactiveTransactionStatus status) throws TransactionException;
106+
107+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.transaction;
18+
19+
import reactor.core.publisher.Mono;
20+
21+
/**
22+
* Representation of the status of a transaction exposing a reactive
23+
* interface.
24+
*
25+
* <p>Transactional code can use this to retrieve status information,
26+
* and to programmatically request a rollback (instead of throwing
27+
* an exception that causes an implicit rollback).
28+
*
29+
* @author Mark Paluch
30+
* @since 5.2
31+
* @see #setRollbackOnly()
32+
* @see ReactiveTransactionManager#getTransaction
33+
*/
34+
public interface ReactiveTransactionStatus {
35+
36+
/**
37+
* Return whether the present transaction is new; otherwise participating
38+
* in an existing transaction, or potentially not running in an actual
39+
* transaction in the first place.
40+
*/
41+
boolean isNewTransaction();
42+
43+
/**
44+
* Set the transaction rollback-only. This instructs the transaction manager
45+
* that the only possible outcome of the transaction may be a rollback, as
46+
* alternative to throwing an exception which would in turn trigger a rollback.
47+
* <p>This is mainly intended for transactions managed by
48+
* {@link org.springframework.transaction.reactive.support.TransactionalOperator} or
49+
* {@link org.springframework.transaction.interceptor.ReactiveTransactionInterceptor},
50+
* where the actual commit/rollback decision is made by the container.
51+
* @see org.springframework.transaction.reactive.support.ReactiveTransactionCallback#doInTransaction
52+
* @see org.springframework.transaction.interceptor.TransactionAttribute#rollbackOn
53+
*/
54+
void setRollbackOnly();
55+
56+
/**
57+
* Return whether the transaction has been marked as rollback-only
58+
* (either by the application or by the transaction infrastructure).
59+
*/
60+
boolean isRollbackOnly();
61+
62+
/**
63+
* Flush the underlying session to the datastore, if applicable.
64+
* <p>This is effectively just a hint and may be a no-op if the underlying
65+
* transaction manager does not have a flush concept. A flush signal may
66+
* get applied to the primary resource or to transaction synchronizations,
67+
* depending on the underlying resource.
68+
*/
69+
Mono<Void> flush();
70+
71+
/**
72+
* Return whether this transaction is completed, that is,
73+
* whether it has already been committed or rolled back.
74+
* @see ReactiveTransactionManager#commit
75+
* @see ReactiveTransactionManager#rollback
76+
*/
77+
boolean isCompleted();
78+
}

0 commit comments

Comments
 (0)