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

MyBatis needs to access java.lang and java.util . Not working anymore by default in Java 17 #2383

Closed
keiki85 opened this issue Nov 15, 2021 · 10 comments

Comments

@keiki85
Copy link

keiki85 commented Nov 15, 2021

Hello MyBatis,

I try to upgrade our application to Java 17. Sadly I hit a few bumps on the way. With Java 17 you can't anymore allow reflection for anyone with --illegel-access=permit.
From my understanding the proper way to fix this, is that mybatis supports the Java module system and correctly specify what it needs. So it is not an unnamed module anymore.
Current package it tries to access are java.lang and java.util (accessing List). For the 2nd one I can provide the stacktrace soon as well, if you need it.

Can you please help me out?
Thank you very much.

MyBatis version

3.5.7

Database vendor and version

MySQL 8.0.17

Test case or example project

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final long java.lang.Long.value accessible: module java.base does not "opens java.lang" to unnamed module @7334aada at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178) at java.base/java.lang.reflect.Field.setAccessible(Field.java:172) at org.apache.ibatis.reflection.invoker.GetFieldInvoker.invoke(GetFieldInvoker.java:38) at org.apache.ibatis.reflection.wrapper.BeanWrapper.getBeanProperty(BeanWrapper.java:164) at org.apache.ibatis.reflection.wrapper.BeanWrapper.get(BeanWrapper.java:49) at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122) at org.apache.ibatis.executor.keygen.SelectKeyGenerator.processGeneratedKeys(SelectKeyGenerator.java:76)

Workaround

Workaround is to add following statement to the java process that opens.

--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED

@harawata
Copy link
Member

harawata commented Nov 15, 2021

Hello @keiki85 ,

It seems that you incorrectly specify keyProperty.
If you need further assistance, please create a small demo project like these and share it on your GitHub repo.

@keiki85
Copy link
Author

keiki85 commented Nov 16, 2021

Hey @harawata . Thanks for the fast reply.

I thought this is a more general issue with Java 17 that's why I didn't thought about creating an example project yet. Or digging more into my personal configuration.
With Java 11 I don't have any issues though. I see what I can provide.

@keiki85
Copy link
Author

keiki85 commented Nov 16, 2021

I found the cause for the first issue.

We have following code:

@Update("UPDATE SEQUENCE_TABLE SET ID = LAST_INSERT_ID(ID+1)") @SelectKey(statement = "SELECT LAST_INSERT_ID() as value", keyProperty = "value", before = false, resultType = Long.class) long createId( LongRef updatedId );

The problem is that "value" is on one hand the field/getter name in "LongRef", but also in the resulting java.lang.Long itself. That's why in org/apache/ibatis/executor/keygen/SelectKeyGenerator.java:75 the test succeeds for having a getter for java.lang.Long value field and tries to make it accessible.

After changing the field name to "number" in LongRef and the result of the query everthingy works fine as it doesn't find any getter.

@GeorgeSalu
Copy link

@keiki85 are you running mybatis on java 17 with no problems?

@keiki85
Copy link
Author

keiki85 commented Nov 17, 2021

@GeorgeSalu Not yet that's why I'm here. Most works fine though.

The next issue I'm facing is related to ognl. I could add "--add-open" to it, but is not a long term fix.
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.ImmutableCollections$List12.isEmpty() accessible: module java.base does not "opens java.util" to unnamed module @55740540 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199) at java.base/java.lang.reflect.Method.setAccessible(Method.java:193) at org.apache.ibatis.ognl.AccessibleObjectHandlerPreJDK9.setAccessible(AccessibleObjectHandlerPreJDK9.java:58) at org.apache.ibatis.ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:1232) at org.apache.ibatis.ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1979) at org.apache.ibatis.ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68) at org.apache.ibatis.ognl.OgnlRuntime.callMethod(OgnlRuntime.java:2055) at org.apache.ibatis.ognl.ASTMethod.getValueBody(ASTMethod.java:97) 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.ASTAnd.getValueBody(ASTAnd.java:61) 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:586) at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:550) 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.ChooseSqlNode.apply(ChooseSqlNode.java:35) at org.apache.ibatis.scripting.xmltags.MixedSqlNode.lambda$apply$0(MixedSqlNode.java:32) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:32) at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:39) at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:305) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:87) at jdk.internal.reflect.GeneratedMethodAccessor45.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64) at jdk.proxy2/jdk.proxy2.$Proxy91.query(Unknown Source) at jdk.internal.reflect.GeneratedMethodAccessor45.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64) at jdk.proxy2/jdk.proxy2.$Proxy91.query(Unknown Source) at jdk.internal.reflect.GeneratedMethodAccessor45.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)

@keiki85
Copy link
Author

keiki85 commented Nov 17, 2021

Looks like ognl is setting isEmpty (of java/util/ImmutableCollections.java:574) "accessible". Even though it's already callable, but not "accessible" as term of java reflection. I guess I create a ticket for them...

@harawata
Copy link
Member

harawata commented Nov 17, 2021

@keiki85 ,

That error may occur if you write <if test="x.isEmpty()">.
Try <if test="x.empty"> or <if test="x.isEmpty"> instead.

isEmpty is one of the Pseudo-Properties for Collections.

@keiki85
Copy link
Author

keiki85 commented Nov 17, 2021

@harawata Thank you very much! That solved my issue.

I'm using isEmpty without brackets now.

So far I have no further issues. Seems like the issue was only the false use of the library.

@onefawn
Copy link

onefawn commented Sep 12, 2024

如果您编写 .尝试或改为。<if test="x.isEmpty()">``<if test="x.empty">``<if test="x.isEmpty">

isEmptyCollections 的伪属性之一。

通过这个解决了问题,thanks

@hazendaz
Copy link
Member

Replaced my comment. Please open new issues rather than comments on years old tickets. Also please write in English.

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

No branches or pull requests

5 participants