java - Method with @Transactional called on target not on proxy instance -
i'm migrating 1 of projects form "self configured spring" spring boot. while of stuff working have problem @transactional method when called context not present set before due call "target" instance instead of "proxy" instance (i'll try elaborate below).
first stripped down view of class hierarchy:
@entity public class config { // fields , stuff } public interface exporter { int startexport() throws exporterexception; void setconfig(config config); } public abstract class exporterimpl implements exporter { protected config config; @override public final void setconfig(config config) { this.config = config; // this.config valid config instance here } @override @transactional(readonly = true) public int startexport() throws exporterexception { // this.config null here } // other methods including abstract 1 subclass } @scope("prototype") @service("cars2exporter") public class cars2exporterimpl extends exporterimpl { // override abstract methods , other // not touching startexport() } // there other implementations of exporterimpl // in implementations problem occurs the calling code this:
@inject private provider<exporter> cars2exporter; public void scheduleexport(config config) { exporter exporter = cars2exporter.get(); exporter.setconfig(config); exporter.startexport(); // i'm wrapping here in class implementing runnable // , put in queue of `taskexecutor` issue happens // on direct call too. :( } what issue?
in call startexport() field config of exporterimpl null although has been set right before.
what found far: breakpoint @ exporter.startexport(); checked id of exporter instance shown eclipse debugger. in debbug round while writing post 16585. continuing execution call/first line of startexport() checked id again (of this time) expecting same realizing not. 16606 here... call startexport() done on instance of class... in previous debug round checked wich instance/id call setconfig() going... first on (16585 in case). explains why config field null in 16606 instance.
to understand happens between line call exporter.startexport(); , actuall first line of startexport() clicked steps between both lines in eclipse debugger.
there came line 655 in cglibaopproxy looks this:
retval = new cglibmethodinvocation(proxy, target, method, args, targetclass, chain, methodproxy).proceed();
checking arguments here found proxy instance id 16585 , target 1 16606.
unfortunately i'm not deep springs aop stuff know if how should be...
i wonder why there 2 instances called on diffrent methods. call setconfig() goes proxy instance , call startexport() reaches target instance , not have access config set...
as mentioned project has been migrated spring boot before using athens-release version of spring platform bom. can tell there no special aop configurations before migration , no explicitly set values after migration.
to problem fixed (or @ least somehow working) tried multiple things:
- remove @scope sub class
- move @transactional method level class
- override startexport() in subclass , put @transactional here
- add @enableaspectjautoproxy application class (i wasn't able log in - no error message)
- set spring.aop.proxy-target-class true
- the above in diffrent combinations...
currently i'm out of clues on how working...
thanks in advance
*hopes can help*
spring boot tries create cglib proxy, class based proxy, before had interface based (jdk dynamic proxy).
due subclass of cars2exporterimpl created , methods overridden , advices applied. setconfig method final cannot overridden , result method called on proxy instead on proxied instance.
so either remove final keyword cglib proxy can created or explicitly disable class based proxies transactions. add @enabletransationmanagement(proxy-target-class=false) should trick. unless there else triggering class based proxies is.
Comments
Post a Comment