Skip to content
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

Getting "NoSuchPropertyException" Randomly #623

Closed
infear-on-the-way opened this issue Apr 2, 2016 · 37 comments
Closed

Getting "NoSuchPropertyException" Randomly #623

infear-on-the-way opened this issue Apr 2, 2016 · 37 comments

Comments

@infear-on-the-way
Copy link

infear-on-the-way commented Apr 2, 2016

Hi,

We are using mybatis-3.3.0. Recently we got one strange error from mybatis code while executing a query that gets executed successfully many times during the day, but failed several times.

Below is the stacktrace:

org.apache.ibatis.ognl.NoSuchPropertyException: OrderXEO.cinemaAddress
    at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:46) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:280) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:80) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:73) ~[mybatis-3.3.0.jar:3.3.0]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358) ~[mybatis-spring-1.2.2.jar:1.2.2]
    ... 36 more
Caused by: org.apache.ibatis.ognl.NoSuchPropertyException: OrderXEO.cinemaAddress
    at org.apache.ibatis.ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:151) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:2434) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:114) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:141) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.ASTNotEq.getValueBody(ASTNotEq.java:50) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:61) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:494) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:458) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:44) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:280) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:80) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113) ~[mybatis-3.3.0.jar:3.3.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:73) ~[mybatis-3.3.0.jar:3.3.0]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358) ~[mybatis-spring-1.2.2.jar:1.2.2]

Any help to find root cause of above error will be greatly appreciated.
Ps. We have met a similar problem(#199) when using mybatis-3.1.0, which has fixed in mybatis-3.3.0. Is this the same cause?

MyBatis version

3.3.1

Database vendor and version

Test case or example project

Steps to reproduce

Expected result

Actual result

@emacarron
Copy link
Member

Unfortunately that was fixed by upgrading OGNL but I am afraid we already are in the latest version. I would suggest trying to isolate the case and pass it to the OGNL project.

@infear-on-the-way
Copy link
Author

Thanks for your reply @emacarron. I'm sorry that did you mean this case had been fixed in mybatis-3.3.1? Is this the problem of OGNL project like that in #199 ?

@emacarron
Copy link
Member

emacarron commented Apr 9, 2016

Yes. Looks like a OGNL problem but we already are in the latest version.

BTW, ognl repo is here, maybe Lukasz knows what to do, please open an issue there.
https://github.com/jkuhnert/ognl

@lukaszlenart
Copy link

3.0.11 isn't the latest OGNL version, maybe you should try to upgrade to the latest one to fix this issue.

@harawata
Copy link
Member

harawata commented May 4, 2016

@infear-on-the-way ,
Could you try upgrading to 3.4.0 or 3.3.1?

MyBatis 3.3.0 includes OGNL 3.0.11
MyBatis 3.3.1 = OGNL 3.1.2
MyBatis 3.4.0 = OGNL 3.1.2

And...thanks for the comment, @lukaszlenart :-)

@infear-on-the-way
Copy link
Author

Thanks for your apply @lukaszlenart @harawata . I will try to upgrade MyBatis to 3.3.1, but could you help to tell the cause of the problem and the difference between these two versions?

@lukaszlenart
Copy link

Here you have the whole list of changes to OGNL 3.1.2 https://github.com/jkuhnert/ognl#release-notes---version-312 and probably your issue is related to this https://issues.apache.org/jira/browse/OGNL-252

@emacarron
Copy link
Member

Thank you @lukaszlenart !

@infear-on-the-way did you have a chance to check newer MyBatis versions? Can we close this issue?

@rwtq2ksw
Copy link

rwtq2ksw commented Jun 17, 2016

I have the same issue with MyBatis 3.4.0, using Spring 4.3.0.RELEASE and MyBatis-Spring 1.3.0. On server start, the first requests fails; but execute correctly the same requests after. The property name change randomly. The properties, of course, exists in the object.

Stacktrace:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'filter.dialAux!=null'. Cause: org.apache.ibatis.ognl.NoSuchPropertyException: com.project.commons.dto.EventViewDto.dialAux
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:79)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:447)
    at com.sun.proxy.$Proxy180.selectList(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:231)
    at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:128)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:68)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53)
    at com.sun.proxy.$Proxy183.select(Unknown Source)
    at com.project.business.service.BaseService.select_aroundBody0(BaseService.java:15)
    at com.project.business.service.BaseService$AjcClosure1.run(BaseService.java:1)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:66)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:72)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:70)
    at com.project.business.service.BaseService.select(BaseService.java:14)
    at com.project.wsrest.controller.EventController.find_aroundBody2(EventController.java:52)
    at com.project.wsrest.controller.EventController$AjcClosure3.run(EventController.java:1)
    at org.springframework.cache.aspectj.AbstractCacheAspect.ajc$around$org_springframework_cache_aspectj_AbstractCacheAspect$1$2bc714b5proceed(AbstractCacheAspect.aj:64)
    at org.springframework.cache.aspectj.AbstractCacheAspect$AbstractCacheAspect$1.invoke(AbstractCacheAspect.aj:71)
    at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:345)
    at org.springframework.cache.interceptor.CacheAspectSupport$1.call(CacheAspectSupport.java:367)
    at org.springframework.cache.ehcache.EhCacheCache.loadValue(EhCacheCache.java:99)
    at org.springframework.cache.ehcache.EhCacheCache.get(EhCacheCache.java:86)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:364)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:327)
    at org.springframework.cache.aspectj.AbstractCacheAspect.ajc$around$org_springframework_cache_aspectj_AbstractCacheAspect$1$2bc714b5(AbstractCacheAspect.aj:80)
    at com.project.wsrest.controller.EventController.find(EventController.java:50)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at com.project.wsrest.filter.ExceptionFilter.doFilter(ExceptionFilter.java:32)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at com.project.wsrest.filter.LoggerFilter.doFilter(LoggerFilter.java:40)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.filters.RemoteIpFilter.doFilter(RemoteIpFilter.java:840)
    at org.apache.catalina.filters.RemoteIpFilter.doFilter(RemoteIpFilter.java:870)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:190)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.ibatis.builder.BuilderException: Error evaluating expression 'filter.dialAux!=null'. Cause: org.apache.ibatis.ognl.NoSuchPropertyException: com.project.commons.dto.EventViewDto.dialAux
    at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:46)
    at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32)
    at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34)
    at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
    at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55)
    at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
    at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41)
    at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
    at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:81)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:434)
    ... 80 more
Caused by: org.apache.ibatis.ognl.NoSuchPropertyException: com.project.commons.dto.EventViewDto.dialAux
    at org.apache.ibatis.ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:151)
    at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:2420)
    at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:114)
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
    at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:141)
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
    at org.apache.ibatis.ognl.ASTNotEq.getValueBody(ASTNotEq.java:50)
    at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
    at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:494)
    at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:458)
    at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:44)
    ... 95 more

@harawata
Copy link
Member

Hi @rwtq2ksw ,

Thanks for the info.
Do these properties have public getter methods?

The property name change randomly.

This implies that the problem involves race condition.
Could you try debugging the code and see what is happening there?
If you could provide a demo app that reproduces the issue, that would be really helpful as well.

@rwtq2ksw
Copy link

Yes, all properties have public getter methods.
I tried debug the code, but i can't reproduce the bug during debugging. Only fail when multiple requests run at the same time before server start. The same requests, launch sequentially, or before the first request response, run correctly.

@harawata
Copy link
Member

Thank you for trying, @rwtq2ksw !
What if you set a break point only on this line and start the server normally?
If the breakpoint is hit, please check if the local variable m is null or not.

I am trying to figure out what happens by reading the code, but it is tricky and I want to narrow down the possibilities a little bit... 😕

@harawata
Copy link
Member

harawata commented Jun 26, 2016

@infear-on-the-way @rwtq2ksw ,
Are your getter methods override methods of super class/interface with different return types?

This could happen if the getter method generates a synthetic method, in theory.

That exception is thrown if this line is executed.
It happens when both OgnlRuntime#getGetMethod() and OgnlRuntime#getReadMethod() return null.

OgnlRuntime#getGetMethod() could return null when multiple threads reach this line simultaneously.
After the first thread put an entry to the cache at this line, the other threads return null from this line.

And OgnlRuntime#getReadMethod() could return null when the getter generates a synthetic (a.k.a. bridge) method [1].
Due to this JDK bug, java.beans.BeanInfo#getMethodDescriptors() could return synthetic version of the method and isMethodCallable() returns false in that case.

[1] It basically means that the method has a different return type than its super class or interface.
In the following examples, the getId() methods generate synthetic methods.

public interface HasId<T> {
  public T getId();
}

public class Person implements HasId<Integer> {
  public Integer getId() {
    return id;
  }
  // ...
}
public class Parent {
  private Number id;
  public Number getId() {
    return id;
  }
}

public class Child extends Parent {
  public Integer getId() {
    return id;
  }
  // ...
}

@rwtq2ksw
Copy link

rwtq2ksw commented Jun 27, 2016

@harawata, No, sorry, I don't have getter methods override methods of super class/interface. I have a super class, but not override methods.

I tried to debug the Ognl class used in OgnlCache, but I can't access to the source. Eclipse says: Source not found. The OgnlCache.java shows correctly (and Mybatis classes), but Ognl classes no. I'm using Maven to include mybatis.

org.mybatis mybatis 3.4.0

@harawata
Copy link
Member

Hm...OK.
Actually, I have managed to reproduce the issue by writing a demo app, so I think we are on the right track.

To narrow down the possibilities, could you execute the following test case and see if it passes?

@Test
public void testReadMethod() throws Exception {
  assertNotNull(OgnlRuntime.getReadMethod(EventViewDto.class, "dialAux", null));
}

Please make sure to use the same Java version as your server that is experiencing the problem.
Which version of Java do you use, by the way?

I tried to debug the Ognl class used in OgnlCache, but I can't access to the source. Eclipse says: Source not found. The OgnlCache.java shows correctly, but Ognl classes no. I'm use Maven to include mybatis.

Try disabling 'Resolve dependencies from Workspace projects' in the Project Properties -> Maven and then right-click the project -> Maven -> Download Sources.

Thank you for your time!

@dannyliiii
Copy link

Hi @harawata , Has this issue been fixed? I got this problem in Mybatis 3.4.1, and the Java version is I am using is 1.8.0_11. Any suggestion to resolve this problem?

@harawata
Copy link
Member

harawata commented Aug 1, 2016

Hi @dannyliiii

If your problem is the one that I have found, it should be fixed by upgrading to Java version 1.8.0_25 or later (1.8.0_101 is the latest).

If it didn't help, we need your help.
Please...

  • test your solution with MyBatis 3.4.2-SNAPSHOT (see the wiki page for how). It contains the latest OGNL version.
  • post the stack trace.
  • (if it's possible) post the declaration of the class causing the exception including superclasses/interfaces.

@dannyliiii
Copy link

Thanks @harawata

My problem seems gone after updating Java to 1.8.0_101. If it happens again in the future I will test it and let you know.

@harawata
Copy link
Member

harawata commented Aug 1, 2016

Good! Thanks for the info, @dannyliiii !

@kazuki43zoo
Copy link
Member

Hi @infear-on-the-way @rwtq2ksw, Can you resolve this issue via upgrading JDK version ?

@arebya
Copy link

arebya commented Dec 16, 2016

Same error on 1.8.0_40 and 1.8.0_112 when using the demo app apove on MacOS.

@harawata
Copy link
Member

Hi @arebya ,

I have tested the demo app on 1.8.0_40 many times, but could not reproduce the error.
How often does it reproduce?
And please post the output of java -version.

@arebya
Copy link

arebya commented Jan 11, 2017

image

@harawata
Copy link
Member

I am sorry, but I have no idea how it reproduces on your environment.
It never occurs on my Mac with Java 1.8.0_112.
Please let us know if you find the cause.

@salten
Copy link

salten commented Jan 20, 2017

I think I have found the cause of this exception. My Mybatis's version is 3.3.1, and I had this problem too.

I see the ognl source, in OgnlRuntime.java:

/*      */   public static Method getGetMethod(OgnlContext context, Class targetClass, String propertyName)
/*      */     throws IntrospectionException, OgnlException
/*      */   {
/* 1939 */     Method method = cacheGetMethod.get(targetClass, propertyName);
/* 1940 */     if (method != null) {
/* 1941 */       return method;
/*      */     }
/*      */
/* 1944 */     if (cacheGetMethod.containsKey(targetClass, propertyName)) {
/* 1945 */       return null;
/*      */     }
/* 1947 */     method = _getGetMethod(context, targetClass, propertyName);
/* 1948 */     cacheGetMethod.put(targetClass, propertyName, method);
/*      */
/* 1950 */     return method;
/*      */   }

When one thread of mapper called first time, there is not method in the cacheGetMethod instance(1939 line), if this thread runs to 1944 line, another thread of the same mapper called this line too, then one of this two threads runs to 1950 line , another thread cacheGetMethod.containsKey(targetClass, propertyName) will returns null.

Then this Exception occurs.

I am sorry to my english is very poor. But I hope my discovery is usefull to anybody!

@salten
Copy link

salten commented Jan 20, 2017

I add a interceptor of mybatis to fix this problem. when the NoSuchPropertyException occurs, I retry once.

@harawata
Copy link
Member

@salten ,

Please see my comments above #623 (comment) , #623 (comment)

If you got this exception with the recent version of Java 8, please investigate why getReadMethod() returns null.
It should be easy enough to write a test like this (you need to change the class and property name, of course).

@Test
public void testReadMethod() throws Exception {
  assertNotNull(OgnlRuntime.getReadMethod(EventViewDto.class, "dialAux", null));
}

@arebya ,
Have you tried the above test?
If it failed, please let me know how it fails.

@salten
Copy link

salten commented Jan 21, 2017

@harawata
I test this case with the debug tool of eclipse。The source is at below:

import java.beans.IntrospectionException;
import java.lang.reflect.Method;

import org.apache.ibatis.ognl.OgnlException;
import org.apache.ibatis.ognl.OgnlRuntime;

public class NoSuchPropertyExceptionTest {

	public static void main(String[] args) {
		for (int i = 0; i < 2; i++) {
			Caller caller = new Caller();
			caller.start();
		}
	}
}

class Caller extends Thread {

	@Override
	public void run() {

		try {
			Method m = OgnlRuntime.getGetMethod(null, People.class, "name");
			if (m != null) {
				System.out.println(m.getName() + " had got!!");
			} else {
				System.out.println("null had got!!");
			}
		} catch (IntrospectionException e) {
			System.out.println("IntrospectionException occurs:" + e.getMessage());
			e.printStackTrace();
		} catch (OgnlException e) {
			System.out.println("OgnlException occurs:" + e.getMessage());
			e.printStackTrace();
		}
	}
}

class People {

	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

And I add a breakpront at line 1944: if (cacheGetMethod.containsKey(targetClass, propertyName)) {

/*      */   public static Method getGetMethod(OgnlContext context, Class targetClass, String propertyName)
/*      */     throws IntrospectionException, OgnlException
/*      */   {
/* 1939 */     Method method = cacheGetMethod.get(targetClass, propertyName);
/* 1940 */     if (method != null) {
/* 1941 */       return method;
/*      */     }
/*      */
/* 1944 */     if (cacheGetMethod.containsKey(targetClass, propertyName)) {
/* 1945 */       return null;
/*      */     }
/* 1947 */     method = _getGetMethod(context, targetClass, propertyName);
/* 1948 */     cacheGetMethod.put(targetClass, propertyName, method);
/*      */
/* 1950 */     return method;
/*      */   }

when the two threads broke at the breakpoint at line 1944, I let one thread run to the line 1950, then let the two threads go on running, then the result of one thread will null。

There is no relation to the version of jdk, I think. The problem is the method 'getGetMethod' in the OgnlRuntime class in not thread-safed(synchronized).

@harawata
Copy link
Member

You did not read my comments... 😔
I know getGetMethod() can return null.
But it is just the first half of the problem.

getGetMethod() is called from getMethodValue()
Here is the first few lines of the method.

public static final Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence) throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
{
  Object result = null;
  Method m = getGetMethod(context, (target == null) ? null : target.getClass() , propertyName);
  if (m == null)
    m = getReadMethod((target == null) ? null : target.getClass(), propertyName, null);
  ...

As you can see, even if getGetMethod() returned null, NoSuchPropertyException is not thrown if getReadMethod() returned non-null value.
What I am trying to find is how getReadMethod() can return null with Java 8.

@harawata
Copy link
Member

I will close this issue because this is clearly an OGNL issue (stack trace shows MyBatis passes the right parameters to OGNL) and this thread got too long to read.
Please post your findings to orphan-oss/ognl#22
If this issue is fixed in OGNL, it will be applied to MyBatis.

@salten
Copy link

salten commented Jan 22, 2017

@harawata
I don't know what version you used. In my mybatis3.3.1 version, the source which I decompile is :

/*      */   public static final Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence)
/*      */     throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
/*      */   {
/* 1444 */     Object result = null;
/* 1445 */     Method m = getGetMethod(context, (target == null) ? null : target.getClass(), propertyName);
/* 1446 */     if (m == null) {
/* 1447 */       m = getReadMethod((target == null) ? null : target.getClass(), propertyName, 0);
/*      */     }
/* 1449 */     if ((checkAccessAndExistence) && ((
/*      */
/* 1451 */       (m == null) || (!(context.getMemberAccess().isAccessible(context, target, m, propertyName))))))
/*      */     {
/* 1453 */       result = NotFound;
/*      */     }
/*      */ 
/* 1456 */     if (result == null) {
/* 1457 */       if (m != null)
/*      */         try {
/* 1459 */           result = invokeMethod(target, m, NoArguments);
/*      */         } catch (InvocationTargetException ex) {
/* 1461 */           throw new OgnlException(propertyName, ex.getTargetException());
/*      */         }
/*      */       else {
/* 1464 */         throw new NoSuchMethodException(propertyName);
/*      */       }
/*      */     }
/* 1467 */     return result;
/*      */   }

The getReadMethod is :m = getReadMethod((target == null) ? null : target.getClass(), propertyName, 0);
There is not the method which you write:

public static final Object getMethodValue(OgnlContext context, Object target, String propertyName, boolean checkAccessAndExistence) throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
{
  Object result = null;
  Method m = getGetMethod(context, (target == null) ? null : target.getClass() , propertyName);
  if (m == null)
    m = getReadMethod((target == null) ? null : target.getClass(), propertyName, null);
  ...

And the method "getReadMethod" is always return null.......

import java.lang.reflect.Method;

import org.apache.ibatis.ognl.OgnlRuntime;

public class NoSuchPropertyExceptionTest {

	public static void main(String[] args) {
		Method m = OgnlRuntime.getReadMethod(People.class, "name", 0);
		if (m != null) {
			System.out.println(m.getName() + " had got!!");
		} else {
			System.out.println("null had got!!");
			System.exit(1);
		}
	}
}

class People {

	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

Maybe your source version is different to mine......

@harawata
Copy link
Member

@salten ,

Thank you for the follow-up!

MyBatis 3.3.1 (and 3.4.0) includes OGNL 3.1.2.
I didn't realize it, but in OGNL 3.1.2, getReadMethod() always returns null (because wrong parameter is specified in getMethodValue()) as you pointed out.
So, you are right that this exception occurs in MyBatis 3.3.1 or 3.4.0 under heavy load even on Java 8.

In your case, upgrading MyBatis to 3.4.2 may fix the problem because this problem does not exist in the included OGNL [1] even though the race condition in getGetMethod() still exists.
If you have to use 3.3.1, the interceptor solution might be a good workaround.

[1] Note that there still is another getReadMethod() issue with synthetic methods which causes the same exception on Java 6 and 7.

p.s.
He didn't mention, but it would make sense if @arebya specified an older version of OGNL .jar when he ran the demo app on Java 8u112.

@salten
Copy link

salten commented Feb 4, 2017

@harawata
Thank you for the answer.
I have to use 3.3.1, and I added an interceptor to fix this ploblem...

@zhoujiayong
Copy link

You are really genius!

@wrightgithub
Copy link

very good,i have this problem too

@davelet
Copy link

davelet commented Jun 26, 2018

I also run into it...

@ghost
Copy link

ghost commented Mar 1, 2019

@salten
could you please share your custom interceptor code?
or anyone who made it work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests