You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Vernier (Jira)" <ji...@apache.org> on 2021/01/27 17:57:00 UTC

[jira] [Created] (GROOVY-9916) IllegalArgumentException when set null to a boolean field into a closure

Eric Vernier created GROOVY-9916:
------------------------------------

             Summary: IllegalArgumentException when set null to a boolean field into a closure
                 Key: GROOVY-9916
                 URL: https://issues.apache.org/jira/browse/GROOVY-9916
             Project: Groovy
          Issue Type: Bug
    Affects Versions: 3.0.7, 2.5.13
            Reporter: Eric Vernier


The following exception has been thrown by an application in production:
{code}
Caused by: java.lang.IllegalArgumentException: Can not set boolean field c.c.a.a.b.t.b.save.RestoreDataMssqlTask.schemaExistInBackup to null value
	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
	at sun.reflect.UnsafeBooleanFieldAccessorImpl.set(UnsafeBooleanFieldAccessorImpl.java:80)
	at java.lang.reflect.Field.set(Field.java:764)
	at org.codehaus.groovy.reflection.CachedField.setProperty(CachedField.java:76)
	at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2718)
	at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3809)
	at c.c.a.a.b.t.b.save.AbstractRestoreTask.setProperty(AbstractRestoreTask.groovy)
	at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:213)
	at groovy.lang.Closure.setPropertyTryThese(Closure.java:370)
	at groovy.lang.Closure.setPropertyOwnerFirst(Closure.java:364)
	at groovy.lang.Closure.setProperty(Closure.java:353)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setGroovyObjectProperty(ScriptBytecodeAdapter.java:544)
	at c.c.a.a.b.t.b.save.RestoreDataMssqlTask$_execImportDatasource_closure1.doCall(RestoreDataMssqlTask.groovy:86)
{code}

I think the following test class reproduces the problem :
{code:groovy}
class Test {

	private boolean b
	
	static final void main(String... args) {
		new Test().f()
	}
	
	def f() {
		println('set boolean to null')
		b = null
		def closure = { 
			println('set boolean to null inside a closure')
			b = null
		}
		closure()
	}	
}
{code}
The conditions are 1) affect null to a primitive boolean variable, 2) the variable must be an instance field, 3) the affectation must be executed in a closure

With Groovy 2.5.5 no exception.
{code}
$ groovy -version
Groovy Version: 2.5.5 JVM: 1.8.0_265 Vendor: AdoptOpenJDK OS: Windows 10

$ groovy Test
set boolean to null
set boolean to null inside a closure
{code}

But with groovy 2.5.13 or the last stable version 3.0.7 the second affectation failed :
{code}
$ groovy -version
Groovy Version: 3.0.7 JVM: 1.8.0_265 Vendor: AdoptOpenJDK OS: Windows 10

$ groovy Test
set boolean to null
set boolean to null inside a closure
Caught: java.lang.IllegalArgumentException: Can not set boolean field Test.b to null value
java.lang.IllegalArgumentException: Can not set boolean field Test.b to null value
        at Test$_f_closure1.doCall(Test.groovy:14)
        at Test$_f_closure1.doCall(Test.groovy)
        at Test.f(Test.groovy:16)
        at Test$f.call(Unknown Source)
        at Test.main(Test.groovy:6)
{code}

In {{org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation}} the method [castToBoolean()|https://github.com/apache/groovy/blob/ac852d6a53bcb583849cb8db8a1cbede5b097502/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java#L185] takes care of the {{null}} value in accordance with the Groovy truth:
{code:java}
public static boolean castToBoolean(Object object) {
        // null is always false
        if (object == null) {
            return false;
        }
{code}

but the method {{castToBoolean()}} is obviously  never called by [castToType()|https://github.com/apache/groovy/blob/ac852d6a53bcb583849cb8db8a1cbede5b097502/src/main/java/org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.java#L218] when the value is null because the first line of castToType is :
{code:java}
if (object == null) return null;
{code}

How can I deal with this behaviour? I guess I must stuck ith the old 2.5.5 ?




--
This message was sent by Atlassian Jira
(v8.3.4#803005)