Groovy DSL with Java

依然范特西╮ 提交于 2019-12-24 07:04:30

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!