I understand groovy basics - and closures...
I am trying to call groovy from java:
// Patient.java
public class Patient {
//... other data
private Map<String, String> attribStore = new HashMap<String,String>();
// getters/setters for attribStore omitted
public void addAttribute(String key, String val) {
if (!attribStore.containsKey(key)) {
attribStore.put(key, val);
}
}
// GroovyHelper.java
public class GroovyHelper {
private String codeSnippet; // groovy script code
public String evaluateSnippetToString(Binding binding) {
addMethodMissingHandler();
GroovyShell shell = createGroovyShell(binding);
Object result = shell.evaluate(codeSnippet);
return result.toString();
}
// installs a patient in the binding - accesses the patient
// attribStore from groovy
// The missing method is used to create an "attribute" i.e.
// a (key,val) pair in the patient map
private void addMethodMissingHandler() {
codeSnippet = "def attribStore = p.getAttribStore();\n"
+ "Patient.metaClass.methodMissing = \n{"
+ " String methodName, args -> \n"
+ "methodName = methodName.replaceFirst(/^get/, '');\n"
+ "def attrib = methodName[0].toLowerCase() + methodName.substring(1);\n"
+ "if (!attribStore.containsKey(attrib)) { attribStore[attrib] = '0'; }\n"
+ "return attribStore[attrib]; \n" + "}\n" + codeSnippet;
}
}
// junit test code
private Patient p;
private Binding binding;
private GroovyHelper gh;
@Before
public void init() {
p = new PatientBuilder().build();
binding = new Binding();
binding.setVariable("p", p);
gh = new GroovyHelper();
}
@Test //passes
public void testPopulatePatientAttribStore() throws Exception {
p.addAttribute("xyz", "4");
gh.setCodeSnippet("p.getXyz()");
gh.evaluateSnippetToString(binding);
}
@Test
public void testGroovy() throws Exception {
Binding binding = new Binding();
binding.setVariable("p", new Patient()); // new patient
p.addAttribute("xyz", "9");
GroovyShell gs1 = new GroovyShell(binding);
assertEquals("9", gs1.evaluate("p.getXyz()")); // fails??? - expected: <[9]> but was: <[4]>
}
My question is - is the closure holding on to the attribute store of an earlier binding?
What exactly is happening here?
Apologies all for the longish code - I worked on it
- cut down irrelevant code
to shrink it to a minimum - any pointer, "more reading to do" hints?