@Override public <R> R withTransaction(TransactionalOperation<R> operation, TransactionConfiguration transactionConfiguration) { ObjectUtils.argumentNotNull(operation, "TransactionalOperation must be not null"); // check active transaction or create a new one final SyncMongoTransaction tx = getCurrentTransaction().map(t -> SyncMongoTransaction.delegate(t)) .orElseGet(() -> startTransaction(transactionConfiguration)); try { // execute operation return operation.execute(tx); } catch (Exception e) { // check rollback transaction if (tx.getConfiguration().isRollbackOnError() && !tx.isCompleted()) { tx.setRollbackOnly(); } throw e; } finally { try { endTransaction(tx); } catch (Exception e) { throw new DataAccessException("Failed to finalize transaction", e); } } }
@Override public <R> CompletionStage<R> withTransaction(AsyncTransactionalOperation<R> operation, TransactionConfiguration transactionConfiguration) { ObjectUtils.argumentNotNull(operation, "TransactionalOperation must be not null"); // check active transaction or create a new one return getCurrentTransaction() .map(t -> (CompletionStage<AsyncMongoTransaction>) CompletableFuture .completedFuture(AsyncMongoTransaction.delegate(t))) .orElseGet(() -> startTransaction(transactionConfiguration)).thenCompose(tx -> { // execute operation try { return operation.execute(tx).thenApply(r -> new TransactionalOperationResult<>(tx, r)); } catch (Exception e) { // check rollback transaction if (tx.getConfiguration().isRollbackOnError() && !tx.isCompleted()) { tx.setRollbackOnly(); } return CompletableFuture.completedFuture(new TransactionalOperationResult<R>(tx, e)); } }).thenApply(result -> { // finalize transaction endTransaction(result.getTransaction()); // check execution error if (result.getError() != null) { throw new TransactionException("Failed to execute operation", result.getError()); } // return the result return result.getResult(); }); }