Don Branson Don Branson - 3 months ago 12
Groovy Question

Using groovy Eval to process generated expression

I'm trying to create a field mapping to map fields from user-friendly names to member variables in a variety of domain objects. The larger context is that I'm building up an ElasticSearch query based on user-constructed rules stored in a database, but for the sake of MCVE:

class MyClass {
Integer amount = 123
}

target = new MyClass()
println "${target.amount}"

fieldMapping = [
'TUITION' : 'target.amount'
]

fieldName = 'TUITION'
valueSource = '${' + "${fieldMapping[fieldName]}" + '}'
println valueSource

value = Eval.me('valueSource')


The Eval fails. Here's the output:

123
${target.amount}
Caught: groovy.lang.MissingPropertyException: No such property: valueSource for class: Script1
groovy.lang.MissingPropertyException: No such property: valueSource for class: Script1
at Script1.run(Script1.groovy:1)
at t.run(t.groovy:17)


What's necessary to evaluate the generated variable name and return the value
123
? It seems like the real problem is that it's not recognizing that
valueSource
has been defined, not the actual expression held in
valueSource
, but that could be wring, too.

Answer

You're almost there, but you need to use a slightly different mechanism: the GroovyShell. You can instantiate a GroovyShell and use it to evaluate a String as a script, returning the result. Here's your example, modified to work properly:

class MyClass {
    Integer amount = 123
}

target = new MyClass()

fieldMapping = [
        'TUITION' : 'target.amount'
]
fieldName = 'TUITION'

// These are the values made available to the script through the Binding
args = [target: target]

// Create the shell with the binding as a parameter
shell = new GroovyShell(args as Binding)

// Evaluate the "script", which in this case is just the string "target.amount".
// Inside the shell, "target" is available because you added it to the shell's binding.
result = shell.evaluate(fieldMapping[fieldName])

assert result == 123
assert result instanceof Integer