java - @Cacheevict sometimes missing an object in the context (EL1011E) -
i’m fighting error week without result. have legacy spring application upgraded spring 3.2.11.release , hibernate 4.2.15.final. there class containing spring cache annotated methods:
public class groovyformulascriptcompilerimpl implements formulascriptcompiler, cacheflusher<classifyobjectattributeplain>, initializingbean { … @override @cacheable(value="compile_cache", key="'formulaforattribute' + #classifyobjectattribute.getplainid()") public formulascript compile(classifyobjectattributeplain classifyobjectattribute) { ... } @override @cacheevict(value="compile_cache", key="'formulaforattribute' + #arg0.getplainid()") public void flush(classifyobjectattributeplain arg0) { if(logger.isdebugenabled()) logger.debug("flushing formula script attribute id=" + arg0.getplainid() + "[" + arg0.getplaindata().getname() + "]"); } } at moment application event generated causes listeners invoke flush() method declared in several classes including instance of groovyformulascriptcompilerimpl class. flush method called see logger.debug output in log file (see below, @ time 19:39:01,149) evicting item cache must occur after returning method fails due error: "org.springframework.expression.spel.spelevaluationexception: el1011e:(pos 30): method call: attempted call method getplainid() on null context object". results in rolling database transaction. below extraction log file (i shortened hibernate trace messages):
19:39:01,131 debug recwasmodifiedpublicationinterceptor:23 - generating modification event classifyobjectattributeplain id=142... 19:39:01,131 debug defaultlistablebeanfactory:243 - returning cached instance of singleton bean 'trigger.attributewasmodifiedobserver.observable' 19:39:01,131 debug defaultlistablebeanfactory:243 - returning cached instance of singleton bean 'com.ps.service.event.recwasmodifiedflushinglistener#0' 19:39:01,132 debug defaultlistablebeanfactory:243 - returning cached instance of singleton bean 'com.ps.service.event.recwasmodifiedflushinglistener#1' 19:39:01,132 debug defaultlistablebeanfactory:243 - returning cached instance of singleton bean 'com.ps.service.event.recwasmodifiedflushinglistener#2' 19:39:01,132 debug defaultlistablebeanfactory:243 - returning cached instance of singleton bean 'com.ps.service.event.recwasmodifiedflushinglistener#3' 19:39:01,132 debug ctattributewasmodifiedobservingtrigger:79 - generating recwasmodifiedevent classify type = 42 due change of attribute packdowngrade 19:39:01,133 debug ctattributewasmodifiedobservingtrigger:99 - removed observing classify type 42 19:39:01,133 debug classifydatacompilerimpl:76 - flushing classify type id=42 [subs] 19:39:01,148 debug jpadcsdao:948 - flushing classify type id=42 19:39:01,149 debug groovyformulascriptcompilerimpl:111 - flushing formula script attribute id=142[packdowngrade] 19:39:01,155 debug hibernatetransactionmanager:844 - initiating transaction rollback 19:39:01,156 debug hibernatetransactionmanager:571 - rolling hibernate transaction on session [...] 19:39:01,156 debug abstracttransactionimpl:203 - rolling 19:39:01,169 debug jdbctransaction:164 - rolled jdbc connection 19:39:01,169 debug jdbctransaction:126 - re-enabling autocommit 19:39:01,169 debug logicalconnectionimpl:198 - aggressively releasing jdbc connection 19:39:01,169 debug logicalconnectionimpl:232 - releasing jdbc connection 19:39:01,169 debug logicalconnectionimpl:250 - released jdbc connection 19:39:01,170 debug hibernatetransactionmanager:633 - closing hibernate session [...] after transaction 19:39:01,171 debug jdbccoordinatorimpl:182 - hhh000420: closing un-released batch 19:39:01,171 warn changelogeditorcontroller:53 - error parsing request org.springframework.expression.spel.spelevaluationexception: el1011e:(pos 30): method call: attempted call method getplainid() on null context object @ org.springframework.expression.spel.ast.methodreference.throwifnotnullsafe(methodreference.java:135) @ org.springframework.expression.spel.ast.methodreference.getvalueref(methodreference.java:68) @ org.springframework.expression.spel.ast.compoundexpression.getvalueref(compoundexpression.java:63) @ org.springframework.expression.spel.ast.compoundexpression.getvalueinternal(compoundexpression.java:82) @ org.springframework.expression.spel.ast.opplus.getvalueinternal(opplus.java:70) @ org.springframework.expression.spel.ast.spelnodeimpl.getvalue(spelnodeimpl.java:93) @ org.springframework.expression.spel.standard.spelexpression.getvalue(spelexpression.java:89) @ org.springframework.cache.interceptor.expressionevaluator.key(expressionevaluator.java:95) @ org.springframework.cache.interceptor.cacheaspectsupport$cacheoperationcontext.generatekey(cacheaspectsupport.java:448) @ org.springframework.cache.interceptor.cacheaspectsupport.inspectcacheevicts(cacheaspectsupport.java:251) @ org.springframework.cache.interceptor.cacheaspectsupport.inspectaftercacheevicts(cacheaspectsupport.java:227) @ org.springframework.cache.interceptor.cacheaspectsupport.execute(cacheaspectsupport.java:212) @ org.springframework.cache.interceptor.cacheinterceptor.invoke(cacheinterceptor.java:66) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.jdkdynamicaopproxy.invoke(jdkdynamicaopproxy.java:204) @ com.sun.proxy.$proxy60.flush(unknown source) @ com.ps.service.event.recwasmodifiedflushinglistener$1.update(recwasmodifiedflushinglistener.java:32) @ java.util.observable.notifyobservers(observable.java:159) @ com.ps.service.event.recwasmodifiedobservinglistener.onapplicationevent(recwasmodifiedobservinglistener.java:40) @ org.springframework.context.event.simpleapplicationeventmulticaster.multicastevent(simpleapplicationeventmulticaster.java:96) @ org.springframework.context.support.abstractapplicationcontext.publishevent(abstractapplicationcontext.java:334) @ com.ps.service.event.recwasmodifiedpublicationinterceptor.invoke(recwasmodifiedpublicationinterceptor.java:24) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.adapter.methodbeforeadviceinterceptor.invoke(methodbeforeadviceinterceptor.java:51) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.adapter.methodbeforeadviceinterceptor.invoke(methodbeforeadviceinterceptor.java:51) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.adapter.methodbeforeadviceinterceptor.invoke(methodbeforeadviceinterceptor.java:51) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.adapter.methodbeforeadviceinterceptor.invoke(methodbeforeadviceinterceptor.java:51) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.jdkdynamicaopproxy.invoke(jdkdynamicaopproxy.java:204) @ com.sun.proxy.$proxy59.updateclassifyobjectattribute(unknown source) ... what cannot understand why argument arg0 available inside flush method become unavailable in spel context moment later.
below declaration of getplainid() method inside classifyobjectattributeplain class (it contains hibernate caching annotations 2nd level cache globally turned off):
@entity(name="object_attribute_plain") @table(name="fact_attributes") @cache(usage=cacheconcurrencystrategy.read_write,region="rules_cache") @batchsize(size=5) @filter(name="logicaldeletedfilter") public class classifyobjectattributeplain extends plainrecordabstract<classifyobjectattribute> { private long plainid; private static final string seqname="fatr_seq"; @id @column(name="fatr_id") @sequencegenerator(name=seqname,sequencename=seqname,allocationsize=1) @generatedvalue(strategy=generationtype.sequence,generator=seqname) public long getplainid() { return plainid; } public void setplainid(long id) { this.plainid = id; } ... } an important note: error stable not occur if flush method of groovyformulascriptcompilerimpl class called alone, without calling flush methods in other classes mentioned above.
any advice or assumption appreciated.
finally i've solved problem. in case faces it, solution change argument names positional ones:
@cacheevict(value="compile_cache", key="'formulaforattribute' + #p0.getplainid()") public void flush(classifyobjectattributeplain arg0) { log trace messages confirms @cacheevict works:
19:39:35,121 debug annotationcacheoperationsource:108 - adding cacheable method 'flush' attribute: [cacheevictoperation[public void com.ps.service.jpadcsdao.flush(com.ps.dmcl.plain.classifytypeplain)] caches=[compile_cache] | key=''classifytype' + #p0.getplainid()' | condition='',false,false] 19:39:35,122 debug jpadcsdao:949 - flushing classify type id=42 19:39:35,363 trace cacheinterceptor:254 - invalidating cache key classifytype42 operation cacheevictoperation[public void com.ps.service.jpadcsdao.flush(com.ps.dmcl.plain.classifytypeplain)] caches=[compile_cache] | key=''classifytype' + #p0.getplainid()' | condition='',false,false on method public abstract void com.ps.service.cacheflusher.flush(com.ps.dmcl.plainrecord) 19:39:35,366 debug annotationcacheoperationsource:108 - adding cacheable method 'flush' attribute: [cacheevictoperation[public void com.ps.classifydatacompilerimpl.flush(com.ps.dmcl.plain.classifytypeplain)] caches=[compile_cache] | key=''compileddata' + #p0.getplainid()' | condition='',false,false] 19:39:35,366 debug classifydatacompilerimpl:77 - flushing compiled classify type id=42 [subs] 19:39:35,367 trace cacheinterceptor:254 - invalidating cache key compileddata42 operation cacheevictoperation[public void com.ps.classifydatacompilerimpl.flush(com.ps.dmcl.plain.classifytypeplain)] caches=[compile_cache] | key=''compileddata' + #p0.getplainid()' | condition='',false,false on method public abstract void com.ps.service.cacheflusher.flush(com.ps.dmcl.plainrecord) 19:39:35,368 debug annotationcacheoperationsource:108 - adding cacheable method 'flush' attribute: [cacheevictoperation[public void com.ps.groovyformulascriptcompilerimpl.flush(com.ps.dmcl.plain.classifyobjectattributeplain)] caches=[compile_cache] | key=''formulaforattribute' + #p0.getplainid()' | condition='',false,false] 19:39:35,368 debug groovyformulascriptcompilerimpl:112 - flushing formula script attribute id=142[packdowngrade] 19:39:35,369 trace cacheinterceptor:254 - invalidating cache key formulaforattribute142 operation cacheevictoperation[public void com.ps.groovyformulascriptcompilerimpl.flush(com.ps.dmcl.plain.classifyobjectattributeplain)] caches=[compile_cache] | key=''formulaforattribute' + #p0.getplainid()' | condition='',false,false on method public abstract void com.ps.service.cacheflusher.flush(com.ps.dmcl.plainrecord) 19:39:35,369 trace transactioninterceptor:473 - completing transaction [com.ps.controller.ruleeditorserviceimpl.updatederivedattribute2] 19:39:35,369 trace hibernatetransactionmanager:923 - triggering beforecommit synchronization 19:39:35,369 trace hibernatetransactionmanager:936 - triggering beforecompletion synchronization 19:39:35,369 debug hibernatetransactionmanager:753 - initiating transaction commit it resembles post ...spel find null valid object, in case debugging information presented, , error occurs depending on whether method executed alone or accompanied other @cacheevict annotated methods. works error origin still not clear.
Comments
Post a Comment