CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-mongodb--mongodb-driver-sync

The MongoDB Synchronous Driver for Java providing blocking I/O patterns for database operations

Pending
Overview
Eval results
Files

sessions-transactions.mddocs/

Sessions and Transactions

Client sessions for transactions, causally consistent reads, and server session management providing ACID guarantees for multi-document operations.

Capabilities

ClientSession Interface

Primary interface for managing client sessions that enable transactions and causally consistent operations.

/**
 * Client session interface for transactions and causally consistent operations
 */
public interface ClientSession extends AutoCloseable {
    /**
     * Gets the server address this session is pinned to (if any)
     * @return server address or null if not pinned
     */
    ServerAddress getPinnedServerAddress();
    
    /**
     * Checks if this session has an active transaction
     * @return true if transaction is active
     */
    boolean hasActiveTransaction();
    
    /**
     * Gets the current transaction options
     * @return transaction options or null if no active transaction
     */
    TransactionOptions getTransactionOptions();
    
    /**
     * Starts a new transaction with default options
     */
    void startTransaction();
    
    /**
     * Starts a new transaction with specific options
     * @param transactionOptions configuration for the transaction
     */
    void startTransaction(TransactionOptions transactionOptions);
    
    /**
     * Commits the current transaction
     */
    void commitTransaction();
    
    /**
     * Aborts the current transaction
     */
    void abortTransaction();
    
    /**
     * Executes a transaction body with automatic retry logic
     * @param transactionBody the operation to execute in the transaction
     * @return result from the transaction body
     */
    <T> T withTransaction(TransactionBody<T> transactionBody);
    
    /**
     * Executes a transaction body with specific callback options
     * @param transactionBody the operation to execute in the transaction
     * @param options configuration for transaction callback behavior
     * @return result from the transaction body
     */
    <T> T withTransaction(TransactionBody<T> transactionBody, TransactionOptions options);
    
    /**
     * Notifies the session that a message has been sent (internal use)
     * @return true if the session should be considered active
     */
    boolean notifyMessageSent();
    
    /**
     * Notifies the session that an operation has been initiated (internal use)
     * @param operation the operation being initiated
     * @return true if the operation should proceed
     */
    boolean notifyOperationInitiated(Object operation);
    
    /**
     * Closes the session and releases server resources
     */
    void close();
}

Usage Examples:

import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.TransactionOptions;
import com.mongodb.ReadConcern;
import com.mongodb.WriteConcern;

// Basic session usage
try (MongoClient client = MongoClients.create()) {
    try (ClientSession session = client.startSession()) {
        MongoDatabase database = client.getDatabase("mydb");
        MongoCollection<Document> collection = database.getCollection("accounts");
        
        // Perform operations with session for causally consistent reads
        Document account = collection.find(session, Filters.eq("accountId", "12345")).first();
        collection.updateOne(session, 
            Filters.eq("accountId", "12345"), 
            Updates.inc("balance", 100));
    }
}

// Manual transaction control
try (ClientSession session = client.startSession()) {
    try {
        session.startTransaction();
        
        // Transfer money between accounts
        collection.updateOne(session,
            Filters.eq("accountId", "account1"),
            Updates.inc("balance", -100));
            
        collection.updateOne(session,
            Filters.eq("accountId", "account2"), 
            Updates.inc("balance", 100));
        
        session.commitTransaction();
        System.out.println("Transfer completed successfully");
        
    } catch (Exception e) {
        session.abortTransaction();
        System.err.println("Transfer failed, transaction aborted: " + e.getMessage());
        throw e;
    }
}

TransactionBody Interface

Functional interface for defining transaction logic with automatic retry capabilities.

/**
 * Functional interface for transaction body execution
 * Transaction bodies must be idempotent as they may be retried
 */
@FunctionalInterface
public interface TransactionBody<T> {
    /**
     * Executes the transaction logic
     * This method must be idempotent as it may be retried on transient failures
     * @return result of the transaction
     * @throws Exception if the transaction should be aborted
     */
    T execute() throws Exception;
}

Usage Examples:

// Automatic transaction with retry logic
try (ClientSession session = client.startSession()) {
    String result = session.withTransaction(() -> {
        // This lambda must be idempotent
        MongoDatabase database = client.getDatabase("ecommerce");
        MongoCollection<Document> orders = database.getCollection("orders");
        MongoCollection<Document> inventory = database.getCollection("inventory");
        
        // Create order
        Document order = new Document("orderId", UUID.randomUUID().toString())
            .append("customerId", "customer123")
            .append("items", Arrays.asList(
                new Document("productId", "product456").append("quantity", 2)
            ))
            .append("status", "pending")
            .append("createdAt", new Date());
        
        orders.insertOne(session, order);
        
        // Update inventory
        UpdateResult inventoryUpdate = inventory.updateOne(session,
            Filters.eq("productId", "product456"),
            Updates.inc("stock", -2));
        
        if (inventoryUpdate.getMatchedCount() == 0) {
            throw new IllegalStateException("Product not found in inventory");
        }
        
        // Return order ID
        return order.getString("orderId");
    });
    
    System.out.println("Order created with ID: " + result);
}

// Transaction with specific options
TransactionOptions txnOptions = TransactionOptions.builder()
    .readConcern(ReadConcern.SNAPSHOT)
    .writeConcern(WriteConcern.MAJORITY)
    .maxCommitTime(30L, TimeUnit.SECONDS)
    .build();

try (ClientSession session = client.startSession()) {
    Boolean transferResult = session.withTransaction(() -> {
        // Complex business logic
        return performAccountTransfer(session, "from123", "to456", 250.00);
    }, txnOptions);
    
    if (transferResult) {
        System.out.println("Transfer completed successfully");
    }
}

Transaction Configuration

Configuration options for controlling transaction behavior and guarantees.

/**
 * Transaction configuration options
 */
public class TransactionOptions {
    /**
     * Read concern for transaction operations
     */
    private ReadConcern readConcern;
    
    /**
     * Write concern for transaction commit
     */
    private WriteConcern writeConcern;
    
    /**
     * Read preference for transaction operations
     */
    private ReadPreference readPreference;
    
    /**
     * Maximum time for commit operation
     */
    private Long maxCommitTimeMS;
    
    // Builder pattern for configuration
    public static Builder builder() { return new Builder(); }
    
    public static class Builder {
        public Builder readConcern(ReadConcern readConcern);
        public Builder writeConcern(WriteConcern writeConcern);
        public Builder readPreference(ReadPreference readPreference);
        public Builder maxCommitTime(long maxCommitTime, TimeUnit timeUnit);
        public TransactionOptions build();
    }
}

Usage Examples:

// Configure transaction for strong consistency
TransactionOptions strongConsistency = TransactionOptions.builder()
    .readConcern(ReadConcern.SNAPSHOT)
    .writeConcern(WriteConcern.MAJORITY)
    .readPreference(ReadPreference.primary())
    .maxCommitTime(60, TimeUnit.SECONDS)
    .build();

// Configure transaction for performance
TransactionOptions performance = TransactionOptions.builder()
    .readConcern(ReadConcern.LOCAL)
    .writeConcern(WriteConcern.W1)
    .readPreference(ReadPreference.primaryPreferred())
    .maxCommitTime(10, TimeUnit.SECONDS)
    .build();

// Use configuration in session
try (ClientSession session = client.startSession()) {
    session.startTransaction(strongConsistency);
    
    // Perform critical operations requiring strong consistency
    performCriticalUpdate(session);
    
    session.commitTransaction();
}

Session Lifecycle Management

Best practices for managing session lifecycle and resource cleanup.

// Session options configuration
ClientSessionOptions sessionOptions = ClientSessionOptions.builder()
    .causallyConsistent(true)
    .defaultTransactionOptions(TransactionOptions.builder()
        .readConcern(ReadConcern.MAJORITY)
        .writeConcern(WriteConcern.MAJORITY)
        .build())
    .build();

try (ClientSession session = client.startSession(sessionOptions)) {
    // Session operations
}

Advanced Session Usage:

// Long-running session with multiple transactions
try (ClientSession session = client.startSession()) {
    // First transaction
    session.withTransaction(() -> {
        // Batch of related operations
        processBatchOfOrders(session, orderBatch1);
        return null;
    });
    
    // Some non-transactional work
    generateReports(session);
    
    // Second transaction
    session.withTransaction(() -> {
        // Another batch of operations
        processBatchOfOrders(session, orderBatch2);
        return null;
    });
}

// Session with custom retry logic
private <T> T executeWithCustomRetry(ClientSession session, TransactionBody<T> body) {
    int maxRetries = 3;
    int attempts = 0;
    
    while (attempts < maxRetries) {
        try {
            return session.withTransaction(body);
        } catch (MongoException e) {
            attempts++;
            if (attempts >= maxRetries || !isRetryableError(e)) {
                throw e;
            }
            // Wait before retry
            try {
                Thread.sleep(100 * attempts);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(ie);
            }
        }
    }
    throw new RuntimeException("Max retries exceeded");
}

Error Handling in Transactions

Proper error handling patterns for transactional operations.

try (ClientSession session = client.startSession()) {
    session.withTransaction(() -> {
        try {
            // Business logic that might fail
            processPayment(session, paymentInfo);
            updateOrderStatus(session, orderId, "paid");
            sendConfirmationEmail(customerEmail);
            
            return "success";
            
        } catch (PaymentDeclinedException e) {
            // Business logic error - should abort transaction
            updateOrderStatus(session, orderId, "payment_failed");
            throw new RuntimeException("Payment declined: " + e.getMessage());
            
        } catch (EmailServiceException e) {
            // Email failure shouldn't abort financial transaction
            // Log error but continue
            logger.warn("Failed to send confirmation email", e);
            return "success_no_email";
            
        } catch (MongoWriteException e) {
            // Database constraint violation
            logger.error("Database constraint violation", e);
            throw e; // Will cause transaction retry or abort
        }
    });
}

// Handle specific transaction errors
try {
    performTransactionalOperation(session);
} catch (MongoTransactionException e) {
    if (e.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL)) {
        // Retry the entire transaction
        logger.info("Transient transaction error, retrying...");
        // Retry logic here
    } else if (e.hasErrorLabel(MongoException.UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)) {
        // Check if transaction actually committed
        logger.warn("Unknown transaction commit result");
        // Verification logic here
    } else {
        // Permanent failure
        logger.error("Transaction failed permanently", e);
        throw e;
    }
}

Performance Considerations

Guidelines for optimizing transaction performance.

// Keep transactions short and focused
session.withTransaction(() -> {
    // Good: Quick, focused operations
    collection.insertOne(session, document);
    relatedCollection.updateOne(session, filter, update);
    return null;
});

// Avoid in transactions: Long-running operations
session.withTransaction(() -> {
    // Bad: Don't do this in transactions
    // - Large bulk operations
    // - Network calls to external services  
    // - Complex aggregations
    // - File I/O operations
    
    // Better: Do these outside the transaction
    return null;
});

// Batch related operations efficiently
List<WriteModel<Document>> operations = Arrays.asList(
    new InsertOneModel<>(doc1),
    new UpdateOneModel<>(filter1, update1),
    new DeleteOneModel<>(filter2)
);

session.withTransaction(() -> {
    // Efficient: Single bulk operation
    collection.bulkWrite(session, operations);
    return null;
});

// Use appropriate read/write concerns
TransactionOptions fastTxn = TransactionOptions.builder()
    .readConcern(ReadConcern.LOCAL)        // Faster reads
    .writeConcern(WriteConcern.W1)         // Faster writes
    .maxCommitTime(5, TimeUnit.SECONDS)    // Quick timeout
    .build();

TransactionOptions safeTxn = TransactionOptions.builder()
    .readConcern(ReadConcern.SNAPSHOT)     // Consistent reads
    .writeConcern(WriteConcern.MAJORITY)   // Durable writes
    .maxCommitTime(30, TimeUnit.SECONDS)   // Longer timeout
    .build();

Install with Tessl CLI

npx tessl i tessl/maven-org-mongodb--mongodb-driver-sync

docs

change-streams.md

collection-crud.md

connection-management.md

database-operations.md

encryption.md

gridfs.md

index-management.md

index.md

query-aggregation.md

sessions-transactions.md

tile.json