Class TxValidated

java.lang.Object
dmx.fun.spring.TxValidated

@NullMarked @Component public class TxValidated extends Object
Spring component that executes a Validated-returning action inside a managed transaction, automatically rolling back when the result is Validated.isInvalid().

Spring's @Transactional rolls back only when an unchecked exception escapes the annotated method. Since Validated<E,A> captures validation failure as a return value, no exception escapes, and the transaction commits even on invalid outcomes — silently persisting partial writes. TxValidated solves this by inspecting the returned Validated: if Validated.isInvalid() is true, the transaction is marked rollback-only before the template commits.

Quick start

@Service
public class RegistrationService {
    private final TxValidated tx;
    private final UserRepository repo;

    public RegistrationService(TxValidated tx, UserRepository repo) {
        this.tx = tx; this.repo = repo;
    }

    public Validated<NonEmptyList<String>, User> register(RegistrationRequest req) {
        return tx.execute(() ->
            validateName(req)
                .combine(validateEmail(req), (name, email) -> new UserDraft(name, email))
                .map(repo::save)
        );
        // • Valid(user)     → transaction commits
        // • Invalid(errors) → transaction rolls back; partial writes undone
    }
}

Wire this bean by declaring a PlatformTransactionManager in your Spring context. Spring Boot auto-configures one for every registered DataSource.

See Also:
  • Constructor Summary

    Constructors
    Constructor
    Description
    TxValidated(org.springframework.transaction.PlatformTransactionManager txManager)
    Creates a TxValidated backed by the given transaction manager.
  • Method Summary

    Modifier and Type
    Method
    Description
    <E,A> Validated<E,A>
    execute(Supplier<Validated<E,A>> action)
    Executes action inside a transaction using the default TransactionDefinition (propagation REQUIRED, isolation DEFAULT).
    <E,A> Validated<E,A>
    execute(org.springframework.transaction.TransactionDefinition def, Supplier<Validated<E,A>> action)
    Executes action inside a transaction configured by def.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • TxValidated

      public TxValidated(org.springframework.transaction.PlatformTransactionManager txManager)
      Creates a TxValidated backed by the given transaction manager.
      Parameters:
      txManager - the transaction manager; must not be null
      Throws:
      NullPointerException - if txManager is null
  • Method Details

    • execute

      public <E,A> Validated<E,A> execute(Supplier<Validated<E,A>> action)
      Executes action inside a transaction using the default TransactionDefinition (propagation REQUIRED, isolation DEFAULT).

      The transaction commits if the action returns Validated.isValid(). The transaction is rolled back when:

      • the action returns Validated.isInvalid(), or
      • the action throws an unchecked exception (propagates to the caller).
      Type Parameters:
      E - the error accumulation type
      A - the valid value type
      Parameters:
      action - the transactional action; must not be null and must not return null
      Returns:
      the Validated returned by action
      Throws:
      NullPointerException - if action is null or returns null
    • execute

      public <E,A> Validated<E,A> execute(org.springframework.transaction.TransactionDefinition def, Supplier<Validated<E,A>> action)
      Executes action inside a transaction configured by def.

      Use this overload when you need explicit control over propagation, isolation level, timeout, or read-only flag:

      var serializable = new DefaultTransactionDefinition();
      serializable.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
      
      Validated<NonEmptyList<String>, User> result =
          tx.execute(serializable, () -> validateAndPersist(req));
      
      Type Parameters:
      E - the error accumulation type
      A - the valid value type
      Parameters:
      def - the transaction definition; must not be null
      action - the transactional action; must not be null and must not return null
      Returns:
      the Validated returned by action
      Throws:
      NullPointerException - if any argument is null or if action returns null