问题
It has been a couple of days since I started with Groovy. But with all the reading and surfing, I haven't quite been able to figure out how to accomplish what I have in mind. So, please excuse me as a beginner. Would be much grateful for your help, as always.
What I want to achieve is this: I have a Java class, say ServiceClass
that has some methods (getMethod()
, postMethod()
etc) to make some REST GET/POST requests (on its own, it works fine). Now, I want to expose a DSL so that the end-user may just say something like: callService ServiceClass method getMethod
and I have the execution of ServiceClass.getMethod()
What I have been trying so far is this: I got a userCommand
file placed somewhere, that for now just reads: callService ServiceClass
I have a sample.groovy
that just does this now:
class Sample {
def srvc
def callService(srvc) {
this.srvc = srvc
"Calling $srvc"
}
}
I got an integrator.groovy
file that has:
//necessary imports
class Integrator{
def sample = new Sample()
def binding = new Binding([
sample:sample,
ServiceClass: new ServiceClass(),
callService:sample.&callService ])
def shell = new GroovyShell(binding)
def runIt() {
shell.evaluate("userCommand")
}
}
And then to run it from my Java application, I am doing:
public static void main(String[] args) {
Integator i = new Integrator()
i.runIt();
}
But this is just not working. With the above syntax it says:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke method setVariable() on null object....
Could anyone please tell me how do I pass around parameters and create object instances?
回答1:
Update: Consider the following userCommand
file:
File userCommand
:
callService ServiceClass getMethod
Which will be parsed by groovy as callService(ServiceClass).getGetMethod()
. So you need a getProperty
method which reroute the call to the correct method:
File Dsl.groovy
:
class Dsl {
static void main(args) {
new Integrator().runIt()
}
}
class DslDelegate {
def service
def callService(service) {
this.service = service
this
}
def getProperty(String prop) {
if (prop == "getMethod") { service.getMethod() }
else { throw new RuntimeException("Unrecognized property '$prop'") }
}
}
class ServiceClass {
def getMethod() { "serviceClass getMethod" }
}
class Integrator{
def dslDelegate = new DslDelegate()
def binding = new Binding([
ServiceClass: new ServiceClass(),
callService:dslDelegate.&callService ])
def shell = new GroovyShell(binding)
def runIt() {
assert shell.evaluate(new File("userCommand")) ==
"serviceClass getMethod"
}
}
Note I renamed the Sample
class, so it becomes a delegator to ServiceClass
. Now it separates DSL/Service responsibilities.
You can do callService ServiceClass method getMethod
too, but it requires more code.
来源:https://stackoverflow.com/questions/27315115/groovy-dsl-with-java