Skip to content

Commit

Permalink
Polishing.
Browse files Browse the repository at this point in the history
Tweak naming. Add Javadoc and documentation.

See #1628
Original pull request: #4552
  • Loading branch information
mp911de committed Mar 12, 2024
1 parent d721579 commit 77a205c
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.Map;
import java.util.Set;

import org.springframework.data.util.Lazy;
import org.springframework.lang.Nullable;

/**
Expand All @@ -30,14 +29,12 @@
* @author Christoph Strobl
* @since 4.3
*/
class DefaultMongoTransactionOptionsResolver implements MongoTransactionOptionsResolver {
enum DefaultMongoTransactionOptionsResolver implements MongoTransactionOptionsResolver {

static final Lazy<MongoTransactionOptionsResolver> INSTANCE = Lazy.of(DefaultMongoTransactionOptionsResolver::new);
INSTANCE;

private static final String PREFIX = "mongo:";

private DefaultMongoTransactionOptionsResolver() {}

@Override
public MongoTransactionOptions convert(Map<String, String> options) {

Expand All @@ -53,7 +50,7 @@ public String getLabelPrefix() {

private static void validateKeys(Set<String> keys) {

if (!keys.stream().allMatch(SimpleMongoTransactionOptions.KNOWN_KEYS::contains)) {
if (!SimpleMongoTransactionOptions.KNOWN_KEYS.containsAll(keys)) {

throw new IllegalArgumentException("Transaction labels contained invalid values. Has to be one of %s"
.formatted(SimpleMongoTransactionOptions.KNOWN_KEYS));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,59 +64,61 @@
public class MongoTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {

private @Nullable MongoDatabaseFactory dbFactory;
private @Nullable MongoDatabaseFactory databaseFactory;
private MongoTransactionOptions options;
private MongoTransactionOptionsResolver transactionOptionsResolver;
private final MongoTransactionOptionsResolver transactionOptionsResolver;

/**
* Create a new {@link MongoTransactionManager} for bean-style usage.
* <br />
* Create a new {@link MongoTransactionManager} for bean-style usage. <br />
* <strong>Note:</strong>The {@link MongoDatabaseFactory db factory} has to be
* {@link #setDbFactory(MongoDatabaseFactory) set} before using the instance. Use this constructor to prepare a
* {@link MongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}.
* <br />
* {@link #setDatabaseFactory(MongoDatabaseFactory) set} before using the instance. Use this constructor to prepare a
* {@link MongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}. <br />
* Optionally it is possible to set default {@link TransactionOptions transaction options} defining
* {@link com.mongodb.ReadConcern} and {@link com.mongodb.WriteConcern}.
*
* @see #setDbFactory(MongoDatabaseFactory)
* @see #setDatabaseFactory(MongoDatabaseFactory)
* @see #setTransactionSynchronization(int)
*/
public MongoTransactionManager() {}
public MongoTransactionManager() {
this.transactionOptionsResolver = MongoTransactionOptionsResolver.defaultResolver();
}

/**
* Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDatabaseFactory}.
*
* @param dbFactory must not be {@literal null}.
* @param databaseFactory must not be {@literal null}.
*/
public MongoTransactionManager(MongoDatabaseFactory dbFactory) {
this(dbFactory, null);
public MongoTransactionManager(MongoDatabaseFactory databaseFactory) {
this(databaseFactory, null);
}

/**
* Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDatabaseFactory}
* applying the given {@link TransactionOptions options}, if present, when starting a new transaction.
*
* @param dbFactory must not be {@literal null}.
* @param databaseFactory must not be {@literal null}.
* @param options can be {@literal null}.
*/
public MongoTransactionManager(MongoDatabaseFactory dbFactory, @Nullable TransactionOptions options) {
this(dbFactory, MongoTransactionOptionsResolver.defaultResolver(), MongoTransactionOptions.of(options));
public MongoTransactionManager(MongoDatabaseFactory databaseFactory, @Nullable TransactionOptions options) {
this(databaseFactory, MongoTransactionOptionsResolver.defaultResolver(), MongoTransactionOptions.of(options));
}

/**
* Create a new {@link MongoTransactionManager} obtaining sessions from the given {@link MongoDatabaseFactory}
* applying the given {@link TransactionOptions options}, if present, when starting a new transaction.
*
* @param dbFactory must not be {@literal null}.
* @param transactionOptionsResolver
* @param databaseFactory must not be {@literal null}.
* @param transactionOptionsResolver must not be {@literal null}.
* @param defaultTransactionOptions can be {@literal null}.
* @since 4.3
*/
public MongoTransactionManager(MongoDatabaseFactory dbFactory, MongoTransactionOptionsResolver transactionOptionsResolver, MongoTransactionOptions defaultTransactionOptions) {
public MongoTransactionManager(MongoDatabaseFactory databaseFactory,
MongoTransactionOptionsResolver transactionOptionsResolver, MongoTransactionOptions defaultTransactionOptions) {

Assert.notNull(dbFactory, "DbFactory must not be null");
Assert.notNull(databaseFactory, "MongoDatabaseFactory must not be null");
Assert.notNull(transactionOptionsResolver, "MongoTransactionOptionsResolver must not be null");

this.dbFactory = dbFactory;
this.databaseFactory = databaseFactory;
this.transactionOptionsResolver = transactionOptionsResolver;
this.options = defaultTransactionOptions;
}
Expand Down Expand Up @@ -278,12 +280,12 @@ protected void doCleanupAfterCompletion(Object transaction) {
/**
* Set the {@link MongoDatabaseFactory} that this instance should manage transactions for.
*
* @param dbFactory must not be {@literal null}.
* @param databaseFactory must not be {@literal null}.
*/
public void setDbFactory(MongoDatabaseFactory dbFactory) {
public void setDatabaseFactory(MongoDatabaseFactory databaseFactory) {

Assert.notNull(dbFactory, "DbFactory must not be null");
this.dbFactory = dbFactory;
Assert.notNull(databaseFactory, "DbFactory must not be null");
this.databaseFactory = databaseFactory;
}

/**
Expand All @@ -301,8 +303,8 @@ public void setOptions(@Nullable TransactionOptions options) {
* @return can be {@literal null}.
*/
@Nullable
public MongoDatabaseFactory getDbFactory() {
return dbFactory;
public MongoDatabaseFactory getDatabaseFactory() {
return databaseFactory;
}

@Override
Expand All @@ -326,14 +328,14 @@ private MongoResourceHolder newResourceHolder(TransactionDefinition definition,
}

/**
* @throws IllegalStateException if {@link #dbFactory} is {@literal null}.
* @throws IllegalStateException if {@link #databaseFactory} is {@literal null}.
*/
private MongoDatabaseFactory getRequiredDbFactory() {

Assert.state(dbFactory != null,
Assert.state(databaseFactory != null,
"MongoTransactionManager operates upon a MongoDbFactory; Did you forget to provide one; It's required");

return dbFactory;
return databaseFactory;
}

private static MongoTransactionObject extractMongoTransaction(Object transaction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import org.springframework.data.mongodb.core.ReadConcernAware;
import org.springframework.data.mongodb.core.ReadPreferenceAware;
import org.springframework.data.mongodb.core.WriteConcernAware;
import org.springframework.lang.Nullable;

import com.mongodb.Function;
import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.TransactionOptions;
Expand Down Expand Up @@ -115,24 +115,23 @@ public WriteConcern getWriteConcern() {
}

/**
* Map the current options using the given mapping {@link Function}.
* Apply the current options using the given mapping {@link Function} and return its result.
*
* @param mappingFunction
* @return instance of T.
* @param <T>
* @return result of the mapping function.
*/
default <T> T as(Function<MongoTransactionOptions, T> mappingFunction) {
default <T> T map(Function<MongoTransactionOptions, T> mappingFunction) {
return mappingFunction.apply(this);
}

/**
* @return MongoDB driver native {@link TransactionOptions}.
* @see MongoTransactionOptions#as(Function)
* @see MongoTransactionOptions#map(Function)
*/
@Nullable
default TransactionOptions toDriverOptions() {

return as(it -> {
return map(it -> {

if (MongoTransactionOptions.NONE.equals(it)) {
return null;
Expand All @@ -157,7 +156,7 @@ default TransactionOptions toDriverOptions() {

/**
* Factory method to wrap given MongoDB driver native {@link TransactionOptions} into {@link MongoTransactionOptions}.
*
*
* @param options
* @return {@link MongoTransactionOptions#NONE} if given object is {@literal null}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* A {@link TransactionOptionResolver} reading MongoDB specific {@link MongoTransactionOptions transaction options} from
* a {@link TransactionDefinition}. Implementations of {@link MongoTransactionOptions} may choose a specific
* {@link #getLabelPrefix() prefix} for {@link TransactionAttribute#getLabels() transaction attribute labels} to avoid
* evaluating non store specific ones.
* evaluating non-store specific ones.
* <p>
* {@link TransactionAttribute#getLabels()} evaluated by default should follow the property style using {@code =} to
* separate key and value pairs.
Expand All @@ -50,11 +50,11 @@ public interface MongoTransactionOptionsResolver extends TransactionOptionResolv
/**
* Obtain the default {@link MongoTransactionOptionsResolver} implementation using a {@literal mongo:}
* {@link #getLabelPrefix() prefix}.
*
*
* @return instance of default {@link MongoTransactionOptionsResolver} implementation.
*/
static MongoTransactionOptionsResolver defaultResolver() {
return DefaultMongoTransactionOptionsResolver.INSTANCE.get();
return DefaultMongoTransactionOptionsResolver.INSTANCE;
}

/**
Expand All @@ -71,16 +71,16 @@ static MongoTransactionOptionsResolver defaultResolver() {
* <p>
* Splits applicable labels property style using {@literal =} as deliminator and removes a potential
* {@link #getLabelPrefix() prefix} before calling {@link #convert(Map)} with filtered label values.
*
* @param txDefinition
*
* @param definition
* @return {@link MongoTransactionOptions#NONE} in case the given {@link TransactionDefinition} is not a
* {@link TransactionAttribute} if no matching {@link TransactionAttribute#getLabels() labels} could be found.
* @throws IllegalArgumentException for options that do not map to valid transactions options or malformatted labels.
*/
@Override
default MongoTransactionOptions resolve(TransactionDefinition txDefinition) {
default MongoTransactionOptions resolve(TransactionDefinition definition) {

if (!(txDefinition instanceof TransactionAttribute attribute)) {
if (!(definition instanceof TransactionAttribute attribute)) {
return MongoTransactionOptions.NONE;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,14 @@
/**
* A {@link org.springframework.transaction.ReactiveTransactionManager} implementation that manages
* {@link com.mongodb.reactivestreams.client.ClientSession} based transactions for a single
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory}.
* <br />
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory}. <br />
* Binds a {@link ClientSession} from the specified
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory} to the subscriber
* {@link reactor.util.context.Context}.
* <br />
* {@link reactor.util.context.Context}. <br />
* {@link org.springframework.transaction.TransactionDefinition#isReadOnly() Readonly} transactions operate on a
* {@link ClientSession} and enable causal consistency, and also {@link ClientSession#startTransaction() start},
* {@link com.mongodb.reactivestreams.client.ClientSession#commitTransaction() commit} or
* {@link ClientSession#abortTransaction() abort} a transaction.
* <br />
* {@link ClientSession#abortTransaction() abort} a transaction. <br />
* Application code is required to retrieve the {@link com.mongodb.reactivestreams.client.MongoDatabase} via
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseUtils#getDatabase(ReactiveMongoDatabaseFactory)} instead
* of a standard {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getMongoDatabase()} call. Spring
Expand All @@ -68,11 +65,10 @@ public class ReactiveMongoTransactionManager extends AbstractReactiveTransaction

private @Nullable ReactiveMongoDatabaseFactory databaseFactory;
private @Nullable MongoTransactionOptions options;
private MongoTransactionOptionsResolver transactionOptionsResolver;
private final MongoTransactionOptionsResolver transactionOptionsResolver;

/**
* Create a new {@link ReactiveMongoTransactionManager} for bean-style usage.
* <br />
* Create a new {@link ReactiveMongoTransactionManager} for bean-style usage. <br />
* <strong>Note:</strong>The {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory db factory} has to
* be {@link #setDatabaseFactory(ReactiveMongoDatabaseFactory)} set} before using the instance. Use this constructor
* to prepare a {@link ReactiveMongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}.
Expand All @@ -82,7 +78,9 @@ public class ReactiveMongoTransactionManager extends AbstractReactiveTransaction
*
* @see #setDatabaseFactory(ReactiveMongoDatabaseFactory)
*/
public ReactiveMongoTransactionManager() {}
public ReactiveMongoTransactionManager() {
this.transactionOptionsResolver = MongoTransactionOptionsResolver.defaultResolver();
}

/**
* Create a new {@link ReactiveMongoTransactionManager} obtaining sessions from the given
Expand Down Expand Up @@ -113,14 +111,16 @@ public ReactiveMongoTransactionManager(ReactiveMongoDatabaseFactory databaseFact
* starting a new transaction.
*
* @param databaseFactory must not be {@literal null}.
* @param transactionOptionsResolver
* @param transactionOptionsResolver must not be {@literal null}.
* @param defaultTransactionOptions can be {@literal null}.
*
* @since 4.3
*/
public ReactiveMongoTransactionManager(ReactiveMongoDatabaseFactory databaseFactory, MongoTransactionOptionsResolver transactionOptionsResolver,
public ReactiveMongoTransactionManager(ReactiveMongoDatabaseFactory databaseFactory,
MongoTransactionOptionsResolver transactionOptionsResolver,
@Nullable MongoTransactionOptions defaultTransactionOptions) {

Assert.notNull(databaseFactory, "DatabaseFactory must not be null");
Assert.notNull(transactionOptionsResolver, "MongoTransactionOptionsResolver must not be null");

this.databaseFactory = databaseFactory;
this.transactionOptionsResolver = transactionOptionsResolver;
Expand Down Expand Up @@ -163,7 +163,8 @@ protected Mono<Void> doBegin(TransactionSynchronizationManager synchronizationMa

}).doOnNext(resourceHolder -> {

MongoTransactionOptions mongoTransactionOptions = transactionOptionsResolver.resolve(definition).mergeWith(options);
MongoTransactionOptions mongoTransactionOptions = transactionOptionsResolver.resolve(definition)
.mergeWith(options);
mongoTransactionObject.startTransaction(mongoTransactionOptions.toDriverOptions());

if (logger.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ public WriteConcern getWriteConcern() {
return writeConcern;
}

@Override
public String toString() {

return "DefaultMongoTransactionOptions{" + "maxCommitTime=" + maxCommitTime + ", readConcern=" + readConcern
+ ", readPreference=" + readPreference + ", writeConcern=" + writeConcern + '}';
}

@Nullable
private static Duration doGetMaxCommitTime(Map<String, String> options) {

Expand Down Expand Up @@ -123,13 +130,6 @@ private static <T> T getValue(Map<String, String> options, OptionKey key, Functi
return value != null ? convertFunction.apply(value) : null;
}

@Override
public String toString() {

return "DefaultMongoTransactionOptions{" + "maxCommitTime=" + maxCommitTime + ", readConcern=" + readConcern
+ ", readPreference=" + readPreference + ", writeConcern=" + writeConcern + '}';
}

enum OptionKey {

MAX_COMMIT_TIME("maxCommitTime"), READ_CONCERN("readConcern"), READ_PREFERENCE("readPreference"), WRITE_CONCERN(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,22 @@
import org.springframework.lang.Nullable;

/**
* MongoDB-specific transaction metadata.
*
* @author Christoph Strobl
* @since 4.3
*/
public interface TransactionMetadata {

/**
* @return the maximum commit time. Can be {@literal null} if not configured.
*/
@Nullable
Duration getMaxCommitTime();

/**
* @return {@literal true} if the max commit time is configured; {@literal false} otherwise.
*/
default boolean hasMaxCommitTime() {
return getMaxCommitTime() != null;
}
Expand Down
Loading

0 comments on commit 77a205c

Please sign in to comment.