-
-
Notifications
You must be signed in to change notification settings - Fork 970
Apply transactional AST transformation to accessor methods in non-domain classes #15347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 7.0.x
Are you sure you want to change the base?
Conversation
|
Backwards compatibility: |
|
To address the intro/comments: I'm not going to say no to this change if it's optional, but in general, I think this is an extremely bad smell in the code to use transactions on setters. Off the top of my head, here are some of the reasons I think this is bad:
Will take a look at the code once people agree on a path forward. I do think this would have to go into 7.1 and not 7.0 too. @matrei @jamesfredley thoughts? |
Currently we have some service methods in services named like setters (for example, My intention is not to make bean setters/getters transactional, nor to allow transactions to be started during data binding or object hydration. These methods are only used as explicit service-level operations, invoked from application use cases, and are not part of the bean/property specification. To avoid exactly the issues you pointed out (data binding side effects, multiple transactions during object construction, confusion with the Spring transactional model, and unexpected interactions with the bean specification), I plan to adjust the method signatures and naming so that they clearly express application commands (for example, This way, transactional boundaries remain at the service layer, but without giving these methods setter semantics or exposing them to any automatic binding or property access mechanisms. |
Currently, methods whose names start with
get*orset*are explicitly excludedfrom transactional method decoration by
AbstractMethodDecoratingTransformation.While this behavior makes sense for stateful objects such as GORM domain classes
(where getters/setters may trigger lazy-loading, hydration, or expected exceptions),
it can lead to surprising behavior in stateless or prototype-scoped beans, especially
Services and background jobs.
In these cases, annotating a method like
setAsDeleted()orgetOrCreate()with@Transactionalsilently results in the method not participating in a transaction,which may cause data to be flushed and persisted even when an exception is thrown.
This behavior is non-obvious and has been reported as a gotcha by multiple users
(see #14539).
Proposed change
Introduce an opt-in mechanism to allow accessor-style methods (
get*/set*)to be wrapped in transactional logic when explicitly requested.
This preserves the existing default behavior (no transactional decoration for
accessors), while allowing advanced use cases—such as stateless services,
batch jobs, and background processes—to opt in safely.
Rationale
The original exclusion of getters and setters is reasonable for domain classes
and other stateful objects, where invoking accessors inside a transaction can
lead to unexpected side effects.
However, in stateless service-style beans, accessor-prefixed methods are often
used as semantic operations rather than property accessors, and excluding them
from transactional decoration can result in silent and hard-to-debug data
consistency issues.
Making this behavior opt-in avoids breaking existing assumptions while giving
developers an explicit and predictable escape hatch.
Related discussions