Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-7376

ClassCastException when searching for a property inside a with closure

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Duplicate
    • 2.3.11
    • None
    • None
    • None

    Description

      I know this is not ideal, but I couldn't isolate this in a small test case.
      However, my real case is something like this:

      package test
      
      import groovy.transform.CompileStatic;
      
      @CompileStatic
      class Test {
      
      	String testProperty
      	
      	void doSomething(Foo f) {
      		f.with {
      			propertyA = testProperty
      			bar(testProperty)
      		}
      	}
      	
       
      	static void main(String[] args) {
      		def t = new Test()
      		def f = new Foo()
      		t.testProperty = 'test'
      		t.doSomething(f)
      		println f.propertyA
      	}
      }
      
      @CompileStatic
      class Foo {
      
      	String propertyA
      
      	void bar(String param) {
      		println("bar $param")
      	}
      	
      	static class Nested {
      		String propertyB
      	}	
      }
      

      It happens that the row with t.testProperty = 'test' or the one with bar(testProperty) (it depends on how I change the code in ways that in theory should be equivalent with each other) throw a ClassCastException with the following stack trace:

      (when calling bar(...))
      ClassCastException.<init>(String) line: 58	
      GeneratedMethodAccessor1279.invoke(Object, Object[]) line: not available	
      Method.invoke(Object, Object...) line: 606	
      CachedMethod.invoke(Object, Object[]) line: 90	
      MetaClassImpl.invokeMissingProperty(Object, String, Object, boolean) line: 873	
      MetaClassImpl.getProperty(Class, Object, String, boolean, boolean) line: 1852	
      MetaClassImpl.getProperty(Object, String) line: 3689	
      InvoiceIdto.getProperty(String) line: not available	
      InvokerHelper.getProperty(Object, String) line: 168	
      Test$_doSomething_closure2(Closure).getPropertyTryThese(String, Object, Object) line: 321	
      

      Or:

      (when trying to set propertyA value)
      ClassCastException.<init>(String) line: 58	
      GeneratedMethodAccessor1287.invoke(Object, Object[]) line: not available	
      Method.invoke(Object, Object...) line: 606	
      CachedMethod.invoke(Object, Object[]) line: 90	
      CachedMethod(MetaMethod).doMethodInvoke(Object, Object[]) line: 324	
      MetaClassImpl.setProperty(Class, Object, String, Object, boolean, boolean) line: 2661	
      MetaClassImpl.setProperty(Object, String, Object) line: 3701	
      InvoiceIdto.setProperty(String, Object) line: not available	
      InvokerHelper.setProperty(Object, String, Object) line: 191	
      InvoiceListService$_refreshInvoice_closure2(Closure).setPropertyTryThese(String, Object, Object, Object) line: 388	
      

      The ClassCastException message is that Foo$Nested cannot be cast to Foo. In fact, in the following row of the stack trace:

      MetaClassImpl.setProperty(Object, String, Object) line: 3701	
      

      I see the following values for variables:

      • object is my Foo instance
      • property is either 'propertyA' or 'testProperty' (depends on cases)
      • but this is an instance of MetaClassImpl for Foo$Nested rather than for Foo (the toString() is something like groovy.lang.MetaClassImpl@6c720cf6[class test.Foo$Nested]).

      I hope this can give you an idea on what may be going on.
      Removing the static compilation with @TypeChecked(TypeCheckingMode.SKIP) on the equivalent of Test.doSomething does not solve the problem, neither it does if I remove the @CompileStatic from the Foo class declaration.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              mauromol Mauro Molinari
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: