Skip to content

Run Storm-initiated transactions through a JTA transaction manager #504

Description

@zantvoort

Storm participates in JTA transactions today wherever Spring opens them. SpringConnectionProvider acquires through DataSourceUtils, so statements inside a @Transactional method enlist in whatever transaction manager the application has, and SpringExternalTransactionProvider sees that transaction through TransactionSynchronizationManager. Neither knows or cares that the manager is a JTA one.

What Storm does not offer yet is running its own transaction { } block through a JTA manager. SpringTransactionContext.resolveTransactionManager matches a manager by the data source it owns: a ResourceTransactionManager whose resource factory is that data source, or a JpaTransactionManager whose entity manager factory is backed by it. JtaTransactionManager owns no single data source, since a global transaction spans every resource enlisted in it, so an application on JTA gets No TransactionManager found for DataSource ... from a Storm block, and has to fall back to @Transactional for the boundary. The programmatic API should be available there too.

Proposal

Resolve a JtaTransactionManager for Storm-initiated transactions when no resource-bound manager claims the data source. That makes the JTA case work without configuration, and keeps the ambiguity check from #383 meaningful for the case it was written for: an application that configures both a JTA manager and a resource-bound one keeps the resource-bound one for Storm's blocks, rather than reporting ambiguity on every start.

The branch sits behind a class-presence check, the way the JPA branch does, since JtaTransactionManager carries jakarta.transaction types in its signature and that API is not always present.

Options JTA cannot honor

Two TransactionOptions values are refused by a JTA manager in its default configuration:

  • Isolation. JtaTransactionManager rejects a custom isolation level unless allowCustomIsolationLevels is set, because JTA has no portable way to apply one.
  • NESTED propagation. Savepoints are unavailable unless a jakarta.transaction.TransactionManager is configured for suspend and resume.

Whether a manager accepts them is configuration it does not expose, so the option is offered and the refusal translated: a Storm-level message naming the option, the manager and what to configure instead, rather than InvalidIsolationLevelException or NestedTransactionNotSupportedException surfacing to a caller who wrote transaction(isolation = ...).

Scope

A Storm block still binds to one data source, under JTA as under any other manager. A block that touches two data sources fails as it does today; a global transaction across several Storm templates is not what this adds.

JTA without Spring, meaning a Jakarta EE container or a standalone transaction manager driving Storm directly, is a separate piece of work. The default JdbcConnectionProviderImpl verifies the arrived auto-commit state and rejects an enlisted connection, and JdbcTransactionContext drives commit and rollback on the connection itself, neither of which is valid under a container-owned transaction. That needs its own connection provider and an ExternalTransactionProvider reading TransactionSynchronizationRegistry, and stays unexercised in CI without a transaction manager to test against. Worth doing when someone asks for it.

Tasks

  • Resolve JtaTransactionManager for Storm-initiated transactions when no resource-bound manager claims the data source
  • Translate a refused isolation level and NESTED propagation into messages naming the Storm option
  • Tests: resolution with a JTA manager alone and alongside a resource-bound manager, plus the two translations
  • Docs: which manager runs a Storm block, and what JTA accepts, in transactions.md

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspringSpring and Spring Boot integration

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions