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