[ 
https://issues.apache.org/jira/browse/GROOVY-7982?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15623119#comment-15623119
 ] 

Daniel Perano edited comment on GROOVY-7982 at 10/31/16 7:34 PM:
-----------------------------------------------------------------

Gladly. The project consists of mixed Java/Groovy sources which are compiled 
into a single executable jar. The Java Database class is my own and provides 
static access to a singleton database connection. The Groovy code is part of a 
command system that accesses the database. All Groovy sources are compiled and 
placed in the jar at build time and statically referenced by Java code (i.e. 
somewhere in Java code, cmdSys.addCommand(new MyGroovyDatabaseCommand())). This 
is why I don't see how it could be a classloader issue - there is no explicit 
classloading anywhere in the database system, and the code is all running from 
an executable jar launched with java -jar myapplication.jar - no WAR or OSGI or 
anything like that.

The stack trace makes it look to me like an issue with the code generator. If 
I'm reading the exception message correctly, the code is trying to cast a 
reference of type Class<Database> to Database, which of course will fail. This 
is consistent with the decompiled code, which is calling 
ScriptBytecodeAdapter.castToType(Database.class, Database.class), and the 
Javadoc for ScriptBytecodeAdapter.castToType() 
(http://docs.groovy-lang.org/2.4.7/html/api/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.html#castToType(java.lang.Object,%20java.lang.Class))
 seems to confirm this.


was (Author: djperano):
Gladly. The project consists of mixed Java/Groovy sources which are compiled 
into a single executable jar. The Java Database class is my own and provides 
static access to a singleton database connection. The Groovy code is part of a 
command system that accesses the database. All Groovy sources are compiled and 
placed in the jar at build time and statically referenced by Java code (i.e., 
cmdSys.addCommand(new MyGroovyDatabaseCommand())). This is why I don't see how 
it could be a classloader issue - there is no explicit classloading anywhere in 
the database system, and the code is all running from an executable jar 
launched with java -jar myapplication.jar - no WAR or OSGI or anything like 
that.

The stack trace makes it look to me like an issue with the code generator. If 
I'm reading the exception message correctly, the code is trying to cast a 
reference of type Class<Database> to Database, which of course will fail. This 
is consistent with the decompiled code, which is calling 
ScriptBytecodeAdapter.castToType(Database.class, Database.class), and the 
Javadoc for ScriptBytecodeAdapter.castToType() 
(http://docs.groovy-lang.org/2.4.7/html/api/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.html#castToType(java.lang.Object,%20java.lang.Class))
 seems to confirm this.

> CompileStatic causes GroovyCastException when calling static methods on a 
> Java class
> ------------------------------------------------------------------------------------
>
>                 Key: GROOVY-7982
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7982
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 2.4.7
>            Reporter: Daniel Perano
>
> I have a project with mixed Java and Groovy sources. A Gradle build compiles 
> the Java sources with javac and the Groovy sources with groovyc. There is a 
> Java class that provides access to a database via static methods. The 
> relevant methods in this class are shown below:
> {code:Java|title=Database.java}
> public class Database {
>     public boolean alreadyExists(String name){}
>     public boolean alreadyExists(UUID id){}
>     public void save(DataClass data){}
> }
> {code}
> The Groovy code that causes the GroovyCastException to be thrown is shown 
> below:
> {code:Java|title=DBAccess.groovy}
> // name is an instance of java.lang.String
> // data is an instance of DataClass (see Database.java snippet above)
> if(!Database.alreadyExists(name)){
>     Database.save(data)
>     // ...
> }else{
>     // ...
> }
> {code}
> When the Groovy snippet above runs, the call to Database.alreadyExists() 
> produces the following stack trace:
> org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast 
> object 'class mypackage.Database' with class 'java.lang.Class' to class 
> 'mypackage.Database'
>       at 
> org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:405)
>       at 
> org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:319)
>       at 
> org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:232)
>       at 
> org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:603)
>       at myotherpackage.DBAccess.doStuff(DBAccess.groovy:56)
> However, if the if statement is removed, the Database.save() method completes 
> successfully. Decompiling the DBAccess.class file produces the following:
> {code:Java|title=CompiledDBAccess.java}
> if (!((Database)ScriptBytecodeAdapter.castToType(Database.class, 
> Database.class)).alreadyExists(name)) {
>      Database.save((DataClass)data);
>      //...
> } else {
>       //...
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to