[groovy-user] Wrappers and return typecasts

6 views
Skip to first unread message

John Smiljanic

unread,
Mar 16, 2015, 3:49:06 PM3/16/15
to us...@groovy.codehaus.org
The groovy DSL that I work on makes use of a wrapper Object that is defined as follows:

public class ExprEvalWrapper extends org.codehaus.groovy.runtime.wrappers.PojoWrapper implements groovy.lang.GroovyInterceptable

The wrapper is used to implement dynamic invocation and security.  The return of every dynamic method/property call in our system is wrapped in a wrapper.  The wrapper then provides security checking and resolution for other dynamic method/property calls.

I don't have all of the history here about why a wrapper was used instead of one of the more supported mechanisms that are supported by the MOP.  For example, it seems like  ExpandoMetaClass provides what we need.  I suspect that the original engineer (who has since left my company) had his reasons and also likely discussed the design with a groovy team member.

Tabling the discussion of whether I can replace the wrapper with a better supported approach (which I am considering but only in the longer term), I did run into an issue with the wrappers that I wanted to raise here.  Our wrapper solution has been working okay as long as our users (business developers that use our DSL) stick with dynamic typing. However, in order to increase productivity we have been integrating type checking at compile time and the new static typing requirements that has created have created issues.  For example,

1.  Our DSL/groovy provides the ability to create a new method.  This method is invoked dynamically. In order to type the method our developers specify the method return type.  However, if the method happens to return a wrapper than a typecast exception is thrown from the GVM as follows:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast
object 'ExprEvalWrapper@698d6d30' with class
'ExprEvalWrapper' to class 'Row'
  at
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:392)
  at
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:306)
  at
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:227)
  at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:601)
  at
bc4j_testp_kava_Expr_js18mt_js18mtEmpOperationsRowOps_gs.findScott(bc4j_testp_kava_Expr_js18mt_js18mtEmpOperationsRowOps_gs.groovy:11)


2.  Any attempt to use a java/groovy typecast with a wrapped value also fails.

def row = findByKey(<key>) // a dynamic method call whose return value is wrapped
((Row)row).aRowOperation

The Row cast is necessary for type checking (unless the findByKey type is declared, see number 1).  This throws a typecast exception ar RT since the row value is wrapped.

There are a number of ways that I have for working around these issues with wrappers.   However, I was wondering if groovy itself has any special treatment for the Wrapper interface. For example, could groovy perform automatic wrapping/unwrapping as necessary.  I'm wondering how our original engineer even found out about the Wrapper interface and if he expected that they would have some special handling.

Any thoughts?

JR



John Smiljanic

unread,
Mar 16, 2015, 3:51:52 PM3/16/15
to us...@groovy.codehaus.org
I'm working with Groovy 2.3.7

Cédric Champeau

unread,
Mar 17, 2015, 5:23:57 AM3/17/15
to us...@groovy.codehaus.org
Hi John,

Is there any chance you could write a self-contained, limited example of what you do? From what I read, it looks like using a trait to implement the wrapper could be an option but I am still unsure.
-- 
Cédric Champeau
Groovy language developer
http://twitter.com/CedricChampeau
http://melix.github.io/blog

Reply all
Reply to author
Forward
0 new messages